P1219八皇后
这个题是一道USACO的经典dfs,与我见面的时间起码七个月了。
放置n个皇后于n*n棋盘,他们不能互相吃(行,列,对角线),问有几种摆法?于是想到了dfs(自我认为有图的就不用DP)。首先确定好了要枚举的是第i行,边界则是搜索到了n+1行,其次循环判断第j列可不可以放,如果可以放就把这个点同一行以及同一列打上标记,然后继续搜索,回溯,将标记抹去。在这里我们要设一个二维flag来打标记,flag[1][j]=1,flag[2][i+j]=1,flag[3][i-j+n]=1
1.dfs枚举什么要想清楚,这种情况下只需要求解行和列即可,所以只枚举行或列就行
2.对角线的表示方法:x+y相同时为左下到右上,x-y相同时为坐上到右下
3.考虑时间复杂度的话直接给点打标记,别用bool flag看能不能继续,这样慢
代码
1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 using namespace std; 8 int a[50]; 9 int flag[50][50]; 10 int n; 11 int cnt=0; 12 void dfs(int i){//枚举到了第i行 13 if(i>n){//结束了 14 cnt++; 15 if(cnt<=3){ 16 for(int i=1;i<=n;i++){//每次会自动更新 17 cout<<a[i]<<" "; 18 } 19 cout<<endl; 20 } 21 return; 22 } 23 for(int j=1;j<=n;j++){ 24 if(flag[1][j]==0&&flag[2][i+j]==0&&flag[3][i-j+n]==0){ 25 a[i]=j; 26 flag[1][j]=1; 27 flag[2][i+j]=1;//对角线 28 flag[3][i-j+n]=1; 29 dfs(i+1); 30 flag[1][j]=0; 31 flag[2][i+j]=0; 32 flag[3][i-j+n]=0; 33 } 34 } 35 } 36 int main(){ 37 cin>>n; 38 dfs(1); 39 cout<<cnt; 40 }
待到oi十一月,我花开后百花杀。