2. N 皇后问题
分析:
对于一个二维且每行每列解唯一的bool题(无附加条件(有也可以结构体))
我们可以用一个 ans[i]=n ,下标i表示行,数据n表示列的一位数组来模拟
有三个限制条件
分别是行(vis)不能一样,对角线(diag)不能一样,副对角线(condiag)不能一样
我们分别用一维数组模拟,下标存储坐标要求,数据存储标记与否
代码:
1 #include<iostream> 2 #include<cmath> 3 #include<cstdio> 4 using namespace std; 5 int N; 6 int ans[100];//数不对就是溢出了 7 bool vis[100],diag[100],condiag[100];//面向每一行的列 8 int cnt; 9 void print() 10 { 11 for(int i=1;i<=N;i++) 12 printf("%d ",ans[i]); 13 cout<<endl; 14 } 15 void DFS(int x)//第几行 16 { 17 if(x==N+1) 18 { 19 cnt++; 20 // if(cnt<=3) 21 print(); 22 return ; 23 } 24 for(int i=1;i<=N;i++) 25 { 26 int t=x+i,t2=x-i+10; //和与差(差可能<0而越界,因此全部右移) 27 if(vis[i]==0&&diag[t2]==0&&condiag[t]==0) 28 { 29 vis[i]=1; 30 diag[t2]=1; 31 condiag[t]=1; 32 ans[x]=i; 33 34 DFS(x+1); 35 36 vis[i]=0; 37 diag[t2]=0; 38 condiag[t]=0; 39 ans[x]=0; 40 } 41 } 42 43 } 44 int main() 45 { 46 cin>>N; 47 DFS(1); 48 if(cnt==0) 49 cout<<"no solute!"; 50 else 51 cout<<cnt; 52 53 return 0; 54 }
注意事项(调试点):
1.数组一定要开大。结果出现忽然小的数据时检查数组规模
2.abs不要随便用在坐标做差上,验算是否会有误差
(坐标做差害怕越界 最好写越界函数或者整体平移)
3.写完后检查一遍基本的运算有没有写错变量(第26行)
(运算表达式用变量代替,方便更改)
待调试(二维数组如何实现)(代码错误)
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 int N; 5 bool vis[50][50]; 6 int ans[15]; 7 void DFS(int x,int y); 8 void print(); 9 int main() 10 { 11 cin>>N; 12 DFS(1,1); 13 return 0; 14 } 15 void DFS(int x,int y) 16 { 17 if(x==N) 18 { 19 print(); 20 return ; 21 } 22 for(int i=1;i<=N;i++) 23 { 24 if(vis[i][1]==1) continue; 25 for(int j=1;j<=N;j++) 26 { 27 if(vis[i][j]==0) 28 { 29 vis[i][j]=1; 30 ans[i]=j; 31 for(int k=1;k<=N;k++) 32 { 33 if(i+j-k<=0||k+i-j<=0) continue; 34 vis[i][k]=1; 35 vis[k][j]=1; 36 vis[(i+j)-k][k]=1; 37 vis[k+(i-j)][k]=1; 38 } 39 DFS(i,j); 40 vis[i][j]=0; 41 ans[i]=0; 42 for(int k=1;k<=N;k++) 43 { 44 if(i+j-k<=0||k+i-j<=0) continue; 45 vis[i][k]=0; 46 vis[k][j]=0; 47 vis[(i+j)-k][k]=0; 48 vis[k+(i-j)][k]=0; 49 } 50 } 51 } 52 } 53 } 54 void print() 55 { 56 for(int i=1;i<=N;i++) 57 printf("%5d",ans[i]); 58 cout<<endl; 59 }