Kas*_*sra 18 c++ algorithm optimization backtracking time-complexity
我使用Backtracking方法在c ++中编写骑士游览算法.但它似乎太慢或陷入无限循环n> 7(大于7乘7棋盘).
问题是:该算法的时间复杂度是多少?如何优化它?!
骑士之旅的问题可以说明如下:
给定一个有n×n方格的棋盘,找到一个骑士的路径,每个方格只访问一次.
这是我的代码:
#include <iostream>
#include <iomanip>
using namespace std;
int counter = 1;
class horse
{
public:
horse(int);
bool backtrack(int, int);
void print();
private:
int size;
int arr[8][8];
void mark(int &);
void unmark(int &);
bool unvisited(int &);
};
horse::horse(int s)
{
int i, j;
size = s;
for(i = 0; i <= s - 1; i++)
for(j = 0; j <= s - 1; j++)
arr[i][j] = 0;
}
void horse::mark(int &val)
{
val = counter;
counter++;
}
void horse::unmark(int &val)
{
val = 0;
counter--;
}
void horse::print()
{
cout<< "\n - - - - - - - - - - - - - - - - - -\n";
for(int i = 0; i <= size-1 ;i++){
cout <<"| ";
for(int j = 0; j <= size-1 ;j++)
cout << setw(2) << setfill ('0') << arr[i][j]<< " | ";
cout << "\n - - - - - - - - - - - - - - - - - -\n";
}
}
bool horse::backtrack(int x, int y)
{
if(counter > (size * size))
return true;
if(unvisited(arr[x][y])){
if((x-2 >= 0) && (y+1 <= (size-1)))
{
mark(arr[x][y]);
if(backtrack(x-2, y+1))
return true;
else
unmark(arr[x][y]);
}
if((x-2 >= 0) && (y-1 >= 0))
{
mark(arr[x][y]);
if(backtrack(x-2, y-1))
return true;
else
unmark(arr[x][y]);
}
if((x-1 >= 0) && (y+2 <= (size-1)))
{
mark(arr[x][y]);
if(backtrack(x-1, y+2))
return true;
else
unmark(arr[x][y]);
}
if((x-1 >= 0) && (y-2 >= 0))
{
mark(arr[x][y]);
if(backtrack(x-1, y-2))
return true;
else
unmark(arr[x][y]);
}
if((x+2 <= (size-1)) && (y+1 <= (size-1)))
{
mark(arr[x][y]);
if(backtrack(x+2, y+1))
return true;
else
unmark(arr[x][y]);
}
if((x+2 <= (size-1)) && (y-1 >= 0))
{
mark(arr[x][y]);
if(backtrack(x+2, y-1))
return true;
else
unmark(arr[x][y]);
}
if((x+1 <= (size-1)) && (y+2 <= (size-1)))
{
mark(arr[x][y]);
if(backtrack(x+1, y+2))
return true;
else
unmark(arr[x][y]);
}
if((x+1 <= (size-1)) && (y-2 >= 0))
{
mark(arr[x][y]);
if(backtrack(x+1, y-2))
return true;
else
unmark(arr[x][y]);
}
}
return false;
}
bool horse::unvisited(int &val)
{
if(val == 0)
return 1;
else
return 0;
}
int main()
{
horse example(7);
if(example.backtrack(0,0))
{
cout << " >>> Successful! <<< " << endl;
example.print();
}
else
cout << " >>> Not possible! <<< " << endl;
}
Run Code Online (Sandbox Code Playgroud)
上面的例子(n = 7)的输出是这样的:

由于在每一步都有 8 种可能性需要检查,并且必须对每个单元格(减去最后一个单元格)执行此操作,因此该算法的时间复杂度为 O(8^(n^2-1)) = O(8^( n^2)) 其中 n 是棋盘边缘上的方块数量。准确地说,这是最坏情况的时间复杂度(如果没有找到或者是最后一个则探索所有可能性所需的时间)。
至于优化,可以有两种类型的改进:
您正在计算 x-2、x-1、x+1、x+2 以及 y 的计算次数至少是 y 的两倍。我可以建议重写这样的事情:
int sm1 = size - 1;
int xm2 = x - 2;
int yp1 = y + 1;
if((xm2 >= 0) && (yp1 <= (sm1))){
mark(arr[x][y]);
if(backtrack(xm2, yp1))
return true;
else
unmark(arr[x][y]);
}
int ym1 = y-1;
if((xm2 >= 0) && (ym1 >= 0)){
mark(arr[x][y]);
if(backtrack(xm2, ym1))
return true;
else
unmark(arr[x][y]);
}
Run Code Online (Sandbox Code Playgroud)
请注意在后续块中也重用了预先计算的值。我发现这比我预想的更有效;这意味着变量赋值和调用比再次执行操作更快。还可以考虑将sm1 = s - 1;and保存area = s * s;在构造函数中,而不是每次都进行计算。
然而,这(是实现改进而不是算法改进)不会改变时间复杂度顺序,而只会将时间除以某个因子。我的意思是时间复杂度 O(8^(n^2)) = k*8^(n^2) 并且差异将在于较低的 k 因子。
我可以这么想:
counter % 8 == 4例如或更好counter > 2*n && counter % 8 == 4再见
| 归档时间: |
|
| 查看次数: |
14774 次 |
| 最近记录: |