コンテンツ
序文
まず、以前に学習したバックトラッキングフレームワークについて理解しましょう。
- パス:現在行っている選択
- 選択リスト:現時点で可能な選択
- 終了条件:つまり、決定木の最下部に到達すると、これ以上選択できなくなります。
result=[];
def backtrack(路径,选择列表)
if 满足结束条件:
result.add(路径);
return
for 选择 in 选择列表
做选择
backtrack(路径,选择列表)
撤销选择
Nクイーンズ問題
この質問は非常に古典的です。多くの友人がそれを見て、かなり恐れていると思います。今日は、以前に学習したテンプレートに従います。突然、このテンプレートの適用について理解し、理解を深めることができます。
最初にトピックを分析します。
これは与えられたn*nのチェス盤であり、その上にn個のチェスの駒を置き、同じ行、同じ列、左上隅、左下隅、右上隅、および右下隅に1つだけがあることを確認します。チェスの駒。描いて分析しましょう。
まず、最初の行の最初のグリッドから歩くと、2番目の行に到達するとそれ以上進むことができないことがわかります。次に、取り消して戻って別の方法を見つけます。
ここでもう一度行うことはできません。元に戻してから元に戻す必要があります。2番目の行は選択できないため、最初の行に元に戻して再度選択するしかありません。
出来た!!これはほんの一例であり、他のクラスも探し続ける必要があります。ここではこれ以上先に進みません。興味のある生徒は下に降りて上の図を理解してみてください。少し考えてみてください。[パス]は、これらの列にうまく配置された女王よりも小さくありません。 、[リストの選択]行のすべての項目列はすべて女王の選択です(ただし、以下で分析されるいくつかの制限があります)[終了条件]最後の行を超えた場合、ここでは制限チェックを分析します。
行と列は見栄えがよく、主に対角線を分析します
左の対角線xy=1;右の対角線:x + y = 5;わかりました、ここで分析を終了します。コードを見てみましょう。
#include<iostream>
using namespace std;
//这里用4*4来做演示
int n = 4;
int ants;
int rec[4];
//bool check(int x, int y)
//{
// for (int i = 0; i < n; i++)
// {
// if (rec[i] == y)//同一列
// {
// return false;
// }
// if (rec[i] + i == x + y)//右对角线
// {
// return false;
// }
// if (i - rec[i] == x - y)//左对角线
// {
// return false;
// }
// }
// return true;
//}
void dfs(int row)//row当前处理的行
{
if (row == n)//结束条件
{
ants++;
return;
}
for (int col = 0; col < n; col++)
{
bool ok = true;
for (int i = 0; i < row; i++)
{
//检查是否合法,与check一样
if (rec[i] == col || i + rec[i] == row + col || rec[i] - i == col - row)
{
ok = false;
break;
}
}
if (ok)
{
rec[row] = col;//做选择
dfs(row + 1);//进入下一行决策
rec[row] = 0;//回溯,撤销选择
}
}
}
int main()
{
dfs(0);
cout << ants << endl;
return 0;
}
小さなテスト
最終要約
バックトラッキングアルゴリズムはマルチツリートラバーサルの問題です。重要なのは、プレオーダートラバーサルとポストオーダートラバーサルの位置でいくつかの操作を実行することです。アルゴリズムフレームワークは次のとおりです。
def backtrack(...):
for 选择 in 选择列表:
做选择
backtrack(...)
撤销选择
関数を作成 backtrack
するときは、移動した「パス」と現在実行できる「選択リスト」を維持する必要があります。「終了条件」がトリガーされると、結果セットに「パス」が記録されます。。
ある程度、動的計画法の力任せの段階は、バックトラッキングアルゴリズムです。一部の問題には、サブ問題が重複する性質があるというだけです。dpテーブルまたはメモの最適化を使用して、再帰ツリーを大幅に整理し、動的計画法にすることができます。今日の2つの問題には、重複するサブ問題、つまりバックトラッキングアルゴリズムの問題はなく、複雑さが非常に高いことは避けられません。