N皇后问题
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 10350 Accepted Submission(s): 4660
Problem Description
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
Sample Input
1 8 5 0
Sample Output
1 92 10这是一道深搜题目!问题的关键是在剪枝。
下面我们对问题进行分析:
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<stdio.h> #include<string.h> int n; int sum; int vis[3][100]; int p[100]; void dfs(int row){ int i,j,k; if(row==n+1){ sum++; return; } for(i=1;i<=n;i++){ if(vis[0][row-i+n]==0&&vis[1][i]==0&&vis[2][i+row]==0){ vis[0][row-i+n]=vis[1][i]=vis[2][i+row]=1; dfs(row+1); vis[0][row-i+n]=vis[1][i]=vis[2][i+row]=0;//回溯 } } } int main(){ int i,j,k; for(n=1;n<=10;n++){ sum=0; memset(vis,0,sizeof(vis)); dfs(1); p[n]=sum; } while(~scanf("%d",&k)&&k!=0){ printf("%d\n",p[k]); } return 0; }