N皇后问题
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 18785 Accepted Submission(s): 8510
Problem Description
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
Sample Input
1
8
5
0
Sample Output
1
92
10
Author
cgf
Source
2008 HZNU Programming Contest
旧题新做呀。大一的时候就用dfs写过当时好像状态记录弄得很复杂。最近学了状压就用状压的思维写了一波。
status用来记录每列是否已经有旗子,另外还有left,right用来记录对角线不能有俩的情况。其实对角线可以这么考虑:对于左对角线来说每往下一行就是left>>1,同理右对角线也是类似的。就记录这三个状态瞎搞一下就行了。在网上有看到别人用位运算不需要先离线答案,我这个代码蜜汁需要离线,不然也是TLE,求大神帮忙看看是为什么。
#include "cstring"
#include "cstdio"
#include "string.h"
#include "iostream"
using namespace std;
int n;
int ans;
void dfs(int row,int status,int left,int right)
{
if(row>n)
{
ans++;
return;
}
for(int i=1;i<=n;i++)
{
if(((1<<(n-i))&left)||((1<<(n-i))&right))
continue;
if((status&(1<<(n-i)))==0)
{
int newleft=(left)|(1<<(n-i));
newleft>>=1;
int newright=(right)|(1<<(n-i));
newright<<=1;
dfs(row+1,status|(1<<(n-i)),newleft,newright);
}
}
return ;
}
int final_ans[20];
int main()
{
for(int i=1;i<=10;i++)
{
n=i;
ans=0;
dfs(1,0,0,0);
final_ans[i]=ans;
}
while(~scanf("%d",&n)&&n!=0)
printf("%d\n",final_ans[n]);
}