八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻
击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种计算机语言可以解决此问题。——————————摘自《度娘百科》
八皇后问题是回溯与搜索的一个很典型的例子。算法关键就是矩阵上。如果在同一行,则行号相同(列同上)。如果都在“/”对角线上,则行列和相同;如果都在“\"对角线上,则行列差相同。
我们可以以行为条件搜索,放置一个以后定下对角线和列号,就像下面的程序:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<iomanip> 5 using namespace std; 6 bool d[100]={0},b[100]={0},c[100]={0}; //定义行列数组,对角线数组。 7 int sum=0,a[100]; 8 int search(int); 9 int print(); 10 int main() 11 { 12 search(1); //用 search(int)函数计算。 13 } 14 int search(int i) 15 { 16 int j; 17 for(j=1;j<=8;j++) 18 if((!b[j])&&(!c[i+j])&&(!d[i-j+7])) 19 { 20 a[i]=j; //放置皇后。声明占用的行、列、对角线。 21 b[j]=i; 22 c[i+j]=1; 23 d[i-j+7]=1; 24 if(i==n)print(); //若8个皇后都放好,输出。 25 else search(i+1); //继续递归放置皇后,回溯。 26 b[j]=0; 27 c[i+j]=0; 28 d[i-j+7]=0; 29 } 30 } 31 int print() 32 { 33 int i; 34 sum++; //方案数累加 35 cout<<sum<<endl; 36 for(i=1;i<=n;i++) //输出方案 37 cout<<setw(4)<<a[i]; 38 cout<<endl; 39 }
程序是这样的:
其中”92“代表方案,后面的数是第几列(行是从一到八)
解释一下就是(1,8)(2,4)(3,1)(4,3)(5,6)(6,2)(7,7)(8,5)
拓展一下就是变成N皇后问题:
#include<iostream> #include<cstdio> #include<cstdlib> #include<iomanip> using namespace std; bool d[100]={0},b[100]={0},c[100]={0}; int sum=0,a[100],n; //注意里面多了个N。 int search(int); int print(); int main() { cin>>n; //输入N。 search(1); } int search(int i) { int j; for(j=1;j<=n;j++) if((!b[j])&&(!c[i+j])&&(!d[i-j+n-1])) { a[i]=j; b[j]=i; c[i+j]=1; d[i-j+n-1]=1; if(i==n)print(); else search(i+1); b[j]=0; c[i+j]=0; d[i-j+n-1]=0; } } int print() { int i; sum++; cout<<sum<<endl; for(i=1;i<=n;i++) cout<<setw(4)<<a[i]; cout<<endl; }
时间: 2024-11-03 22:43:09