C++でバッタがターゲットに到達できるかどうかを判定する方法
長さ n の文字列 S と整数 k が与えられる問題を考えてみましょう。文字列には4種類の文字が含まれており、それぞれ複数のセル(マス)を表しています。バッタはジャンプを繰り返してターゲットに到達しようとしています。
各文字の意味は以下の通りです。
'.': 対応するセルが空であることを表します'#': 対応するセルに障害物があり、バッタはそこへジャンプできません'G': バッタの開始位置を表します'T': 目標となるターゲットのセルを表します
バッタは現在位置からちょうど k セル先にしかジャンプできません。このとき、バッタがターゲットに到達できるかどうかを判定する必要があります。
例えば、入力が S = "#G#T#"、k = 2 の場合、出力は True になります。これは、G から T までの距離が2セルであり、k も2なので、バッタは1回のジャンプでターゲットに到達できるためです。
解法のアプローチ
この問題を解くためには、以下の手順に従います。
nを文字列SのサイズとしますxをS内の'G'の位置、yを'T'の位置としますx > yの場合は、xとyを入れ替えますiをxで初期化し、i < yの間、iをi + kずつ更新しながらループします- 途中で
S[i]が'#'と一致した場合は、ループを抜けます
- 途中で
- ループ終了時に
i == yであればtrueを返し、そうでなければfalseを返します
このアルゴリズムのポイントは、バッタが必ず k セルずつジャンプするため、開始位置から k 刻みで進んだ位置だけを確認すればよいという点です。障害物にぶつかることなく、ちょうどターゲットの位置に着地できれば到達可能と判断できます。
C++での実装例
理解を深めるために、実際の実装を見てみましょう。
#include <bits/stdc++.h>
using namespace std;
bool solve(string S, int k)
{
int n = S.size();
int i;
int x = S.find('G');
int y = S.find('T');
if (x > y)
swap(x, y);
for (i = x; i < y; i += k)
{
if (S[i] == '#')
break;
}
if (i == y)
return true;
else
return false;
}
int main()
{
string S = "#G#T#";
int k = 2;
cout << solve(S, k) << endl;
}入力
"#G#T#", 2
出力
1
出力が 1(true)となっており、バッタが1回のジャンプでターゲットに到達できることが確認できます。このアルゴリズムの計算量は O(n/k) であり、文字列の長さに対して効率的に動作します。
-
Pythonでジャンプを繰り返して位置nに到達できるかどうかを判定するプログラム
1からnまでの番号が振られた数直線を考えてみましょう。最初は位置0におり、まず1ステップジャンプして位置1へ移動し、次に2ステップジャンプして位置3に到達し、さらに3ステップジャンプして位置6に到達します。このようにジャンプ幅を1ずつ増やしながら進んだとき、最終的に位置nにぴったり到達できるかどうかを判定するのがこの問題です。 例えば、入力が n = 21 の場合、出力は True になります。これは 1+2+3+4+5+6 = 21 となり、6回目のジャンプでちょうど位置21に到達できるためです。 解法のアプローチ この問題は数学的な性質を利用すると効率的に解けます。手順は以下の通りです。
-
Pythonでロボットが目標座標に到達できるか判定するプログラムの書き方
ロボットが2次元座標平面(直交座標系)の原点 (0, 0) にいるとします。ロボットが実行できる移動のリストが与えられ、各移動は N(北)、S(南)、W(西)、E(東) のいずれかです。このロボットが、目的地の座標 (x, y) に到達できるかどうかを判定するプログラムを作成します。 例えば、入力が moves = [N,N,E,E,S]、目的地が (x, y) = (2, 1) の場合、出力は True になります。北に2回、東に2回、南に1回移動することで、最終的に (2, 1) に到達できるからです。 解決のアプローチ この問題は、ロボットの移動を実際にシミュレーションすることで解けます