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 }

 

posted @ 2019-08-01 17:28  毛炯人  阅读(205)  评论(0编辑  收藏  举报