骑士之旅(回溯)
Posted
技术标签:
【中文标题】骑士之旅(回溯)【英文标题】:Knight tour (backtrack) 【发布时间】:2014-03-15 16:50:27 【问题描述】:我正在尝试用 8*8 棋盘解决骑士的巡回赛问题。但是我的回溯是无限循环的。我的逻辑函数如下:-
N 是 8。
boolean algo(int x,int y,int no_of_moves,int sol[][])
if(no_of_moves==N*N)
return true;
int nextx;
int nexty;
for(int i=0;i<8;i++)
nextx=x+move_x[i];
nexty=y+move_y[i];
if(is_valid(nextx,nexty))
sol[nextx][nexty]=no_of_moves;
if(algo(nextx,nexty,no_of_moves+1,sol))
return true;
else
sol[nextx][nexty]=-1;
return false;
sol [][] 存储骑士的动作。
数组 move_x 和 move_y 存储要添加到 x 和 y 以获得骑士的下一个位置的值。
int move_x[]= 2, 1, -1, -2, -2, -1, 1, 2 ;
int move_y[]= 1, 2, 2, 1, -1, -2, -2, -1 ;
我首先将 x 作为 0,y 作为 0,no_of_moves 作为 1,并将 sol[][] 中的所有值作为 -1 除了 sol[0][0] 为 0。
然后is_valid()
检查nextx
和nexty
是否在棋盘内并且尚未访问。
boolean is_valid(int xnext,int ynext)
if(xnext>=0 && xnext<N && ynext>=0 && ynext<N && sol[xnext][ynext]==-1)
return true;
else
return false;
【问题讨论】:
我很确定它不是无限的。它更像 number_of_moves^(N*N)。你确定你检查你是否已经正确地访问了这个领域?最简单的方法是在非常小的板上运行它,比如 3x3,然后检查它是否真的结束了。 您可能希望在问题中包含您的is_valid()
方法,以防出现问题。
boolean is_valid(int xnext,int ynext) if(xnext>=0&&xnext我看不出代码有什么问题。我怀疑它不会进入一个无限循环,而是进入一个需要很长时间的循环。
查看它是否适用于 5x5 板 (animation)。
【讨论】:
我把 System.out.println(no_of_moves);看看它卡在哪里,它显示为:-52 50 51 52 52 53 52 51 52 53 50 51 51 48 49 50 51 52 53 54 55 ...表示卡在50年代 @user3423663:但这并不能证明什么,不是吗?还是我在这里错过了你的观点? 不,我只是说它真的进入了无限循环,时间不长。好吧,我会尝试再次查看我的完整代码,但我真的不知道它是如何发生的。跨度> @user3423663:我仍然不理解你为什么认为循环是无限的,但我将把它留在那里。 你是对的@NPE。它不是无限的,它需要非常非常长的时间。 5*5 用了 5 秒,6*6 棋盘用了 14 秒,8*8 用了 13 多分钟,仍然没有解决方案。谢谢。那么我应该使用哪种算法?【参考方案2】:我看到你在那里使用蛮力,但这不足以在合理的时间内解决这个问题。如果没有优化,复杂度将为O(N^(N*N))
(N 是板尺寸)。因此,找到第一个解决方案可能真的需要很长时间。这就是为什么你认为它处于无限循环中。
最有效的优化是Warnsdorff's rule,它于 1823 年首次发布。它是一种简单的启发式规则,可让您在第一次尝试时(立即)找到解决方案。
【讨论】:
以上是关于骑士之旅(回溯)的主要内容,如果未能解决你的问题,请参考以下文章