我尝试使用回溯为骑士的旅行问题编写代码。我的代码适用于4x4矩阵,但适用于8x8矩阵,但在输出屏幕上未显示任何内容。
我不知道我在做什么错。
这是我的代码的工作方式:
如果所有广场都参观过
#include<iostream>
using namespace std;
#define n 8
int safe(int c[n][n],int i, int j)
{
if((i>=0&&i<n)&&(j>=0&&j<n))
{
if(c[i][j])
return 0;
else
return 1;
}
return 0;
}
int knightstour(int c[n][n],int i,int j,int k)
{
if(k==n*n)
{
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
cout<<c[i][j]<<" ";
cout<<endl;
}
return 1;
}
else
{
c[i][j]=k;
if(safe(c,i+2,j+1))
{
if(knightstour(c,i+2,j+1,k+1))
return 1;
}
if(safe(c,i+2,j-1))
{
if(knightstour(c,i+2,j-1,k+1))
return 1;
}
if(safe(c,i-2,j+1))
{
if(knightstour(c,i-2,j+1,k+1))
return 1;
}
if(safe(c,i-2,j-1))
{
if(knightstour(c,i-2,j-1,k+1))
return 1;
}
if(safe(c,i+1,j+2))
{
if(knightstour(c,i+1,j+2,k+1))
return 1;
}
if(safe(c,i-1,j+2))
{
if(knightstour(c,i-1,j+2,k+1))
return 1;
}
if(safe(c,i+1,j-2))
{
if(knightstour(c,i+1,j-2,k+1))
return 1;
}
if(safe(c,i-1,j-2))
{
if(knightstour(c,i-1,j-2,k+1))
return 1;
}
c[i][j]=0;
return 0;
}
}
int main()
{
int c[n][n]={0};
if(!knightstour(c,0,0,0))
cout<<"solution doesn't exist";
return 1;
}
其他
将下一移动之一添加到解向量并递归 检查此举是否可以解决。 (一个骑士可以最大化 八招。我们在此步骤中选择8个动作之一。
如果在上述步骤中选择的举动没有导致解决方案 然后从解决方案向量中删除此举,然后尝试其他 替代动作。
如果所有替代方法均无效,则返回false(返回false 将以递归方式删除之前添加的项目,如果为false 由最初的递归调用返回,则“不存在解决方案”)
这是我编写的代码:
{{1}}
答案 0 :(得分:3)
暂时假设您的算法是正确的,因为它似乎至少对n == 6
有用:
0 13 20 23 34 11
21 30 35 12 19 24
14 1 22 31 10 33
29 4 7 16 25 18
6 15 2 27 32 9
3 28 5 8 17 26
以下是使用各种n
值运行代码的时钟时间结果:
===== 1 0m 0.001s
===== 2 0m 0.001s
===== 3 0m 0.003s
===== 4 0m 0.002s
===== 5 0m 0.070s
===== 6 0m 35.997s
===== 7 ...
您会注意到我还那里还没有n = 7
的数字,它还在5.5小时并还在计时:-)
由于它将持续至少 个时间(大约330分钟),因此我们可以使用回归分析来计算尺寸8的最小图(使用二次方多项式,仅使用大小为5、6且尚未完成的数据7)(a)。根据这些计算,最少的时间约为16.5小时。
但是,即使不是二次方,对于6x6电路板它跳到36秒,对于7x7电路板至少跳到5.5小时,这意味着您使用的算法不会扩展良好。因此,您可能会发现它正在正常工作,您可能只需要等待一会儿即可。 long 可能是:-)
(a)如果您感兴趣(或想要检查/评论我的方法),这是我的分析。警告:数学运算要提前...
我们有数据集:
x (value of n) y (seconds taken)
-------------- -----------------
5 0.07
6 36.00
7 600.00 (when it had been running ten minutes)
使用公式:
y = ax^2 + bx + c
我们最终得到了联立方程:
0.07 = 25a + 5b + c (1)
36 = 36a + 6b + c (2)
600 = 49a + 7b + c (3)
减去对可得出:
(2) - (1): 35.93 = 11a + b (4)
(3) - (2): 564 = 13a + b (5)
(5) - (4): 528.07 = 2a
所以a = 264.035
。将其代入(5)
将得到b = -2868.455
,将a
和b
代入(3)
将得到c = 7741.47
。将这三个值放到方程(1)
,(2)
和(3)
中可以得到期望值。
那是(从高中时代开始)所用的方法,但是,当然,如果600
数字发生变化时,快速而又肮脏的Python程序可以正常工作,则更好。 :
import sys
y5 = 0.07 ; y6 = 36 ; y7 = int(sys.argv[1]) * 60
a = ((y7 - y6) - (y6 - y5)) / 2
b = (y7 - y6) - 13 * a
c = y7 - 49 * a - 7 * b
y8 = 64 * a + 8 * b + c
print(y8, y8 / 3600)
您可以运行该命令,提供7号尺寸的当前值,它将推出最小数字(以秒和小时为单位)。