HDU 2553(DFS_A题)解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2553

题意:NxN的棋盘,N个皇后,有多少种方法

思路:DFS

1.一行只能放一个皇后,所以我们一旦确定此处可以放皇后,那么该行就只能放一个皇后,下面的就不要再搜了。

2.每一列只能放一个皇后,所以我们下次搜索就不要再搜已经放过的皇后了。

3.斜的45°线也只能放一个。

综上如何才能最快速的确定一列和45°是否用过这个是个关键步骤,一旦此步骤确定我们就可以很快的进行搜索了。

我们用三个数组来保存他的每一个状态及(三个方向 ↖ ↑ ↗)

但是如果我们保存↑(每一列方向上的皇后)是非常容易保存的 但是保存( 这两个方向上的状态就不容易了↖ ↗)

 

再分析,在这个(↖)方向上的数据的行和列有什么特点

 0  1  2  3   4

-1  0  1  2  3

-2 -1  0  1  2

-3 -2 -1  0  1

-4 -3 -2 -1  0 

将此表列出我们就应该知道在(↖)方向上的数据的行和列的特点了,及   在 (↖)方向上  列 - 行 的差是相等的。

假如我们用数组保存负数肯定是不行的, 所以我们要加上 n,让他变为非负.

 

再分析,在这个( ↗)方向上的数据的行和列有什么特点

0 1 2 3 4

1 2 3 4 5

2 3 4 5 6

3 4 5 6 7

将此表列出我们就应该知道在(↗)方向上的数据的行和列的特点了,及   在 (↗)方向上  列 + 行 的和是相等的。

知道数据怎么处理就可以解决问题了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int MAXN =10+10;
int vis[3][MAXN]={{0,0}};
int tot=0;
int ans[11+5]={0};

void search(int cur,int n){
    if(cur==n)    tot++;
    else for(int i=0;i<n;i++){
        if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n]){
            vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=1;
            search(cur+1,n);
            vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=0;
        }
    }
}

int main(void){
    for(int i=1;i<=10;i++){
        for(int i=0;i<3;i++){
            for(int j=0;j<11;j++){
                vis[i][j]=0;
            }
        }
        tot =0;
        search(0,i);
        ans[i]=tot;
    }
    int n=0;
    while(~scanf("%d",&n)&&n!=0){
        printf("%d\n",ans[n]);
    }

    return 0;

}
View Code

 

posted @ 2018-01-28 09:06  caomp  阅读(111)  评论(0)    收藏  举报