Pythonでチェスのナイトが目標位置に到達するまでの最小手数を求めるプログラム
問題の概要
2つの値 r と c が与えられているとします。無限に広いチェス盤上で、ナイト(騎士)が最初に座標 (0, 0) に配置されているとき、そのナイトが位置 (r, c) に到達するまでに必要な最小の移動回数を求めます。
ナイトの動きは通常のチェスと同じで、「横に2マス・縦に1マス」または「縦に2マス・横に1マス」という移動を行います。
例えば、入力が r = 6、c = 1 の場合、出力は 3 となります。下図では、赤が初期位置、緑が最終位置、黄色が途中の経由地点を表しています。

解法のアプローチ
この問題は、ナイトの移動パターンを数学的に分析することで、幅優先探索(BFS)のような反復処理を使わずに、定数時間 O(1) で答えを導けます。解法の手順は以下の通りです。
- ステップ1: もし r < c ならば、r と c を入れ替えます(盤面の対称性を利用)。
- ステップ2: (r, c) が (1, 0) と一致する場合は 3 を返します(例外的なケース)。
- ステップ3: (r, c) が (2, 2) と一致する場合は 4 を返します(例外的なケース)。
- ステップ4: delta := r − c を計算します。
- ステップ5: c > delta の場合、delta − 2 × ((delta − c) ÷ 3 の商) を返します。
- ステップ6: それ以外の場合、delta − 2 × ((delta − c) ÷ 4 の商) を返します。
実装例(Python)
以下のコードで、実際の実装を確認できます。
class Solution:
def solve(self, r, c):
if r < c:
r, c = c, r
if (r, c) == (1, 0):
return 3
if (r, c) == (2, 2):
return 4
delta = r - c
if c > delta:
return delta - 2 * ((delta - c) // 3)
else:
return delta - 2 * ((delta - c) // 4)
ob = Solution()
r = 6
c = 1
print(ob.solve(r, c))
入力
6, 1
出力
3
まとめ
このアルゴリズムのポイントは、ナイトの移動が持つ対称性と数学的な性質を活かしている点です。まず r と c を並べ替えて一般形に帰着させ、(1, 0) と (2, 2) という例外的なケースだけを個別に処理すれば、残りはすべて統一された公式で計算できます。これにより、盤面を実際に探索することなく、最小手数を高速に求めることが可能になります。
-
Pythonで全ノードに到達可能な最小の頂点集合を見つけるプログラム
問題概要有向非巡回グラフ(DAG)を考えます。グラフにはn個の頂点があり、各ノードには0からn-1までの番号が付けられています。グラフはエッジリストとして表現され、edges[i] = (u, v)はノードuからノードvへ向かう有向エッジを意味します。このとき、そこから出発すればグラフ内のすべてのノードに到達できるような、最小の頂点集合を見つける必要があります(頂点は任意の順序で返して構いません)。例えば、入力が次のような場合を考えてみましょう。この場合、出力は [0, 2, 3] となります。これらの頂点は他のどの頂点からも到達できないため、ここから探索を開始すれば全ノードをカバーできるから
-
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) に到達できるからです。 解決のアプローチ この問題は、ロボットの移動を実際にシミュレーションすることで解けます