標籤:杭電 搜尋 回溯
http://acm.hdu.edu.cn/showproblem.php?pid=2553N皇后問題
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8077 Accepted Submission(s): 3603
Problem Description
在N*N的方格棋盤放置了N個皇后,使得它們不相互攻擊(即任意2個皇后不允許處在同一排,同一列,也不允許處在與棋盤邊框成45角的斜線上。
你的任務是,對於給定的N,求出有多少種合法的放置方法。
Input
共有若干行,每行一個正整數N≤10,表示棋盤和皇后的數量;如果N=0,表示結束。
Output
共有若干行,每行一個正整數,表示對應輸入行的皇后的不同放置數量。
Sample Input
1850
Sample Output
19210
這個問題終於理解啦!還記得第一次接觸這個問題時一直在逃避,覺得感覺起來好麻煩,不想去思考,在昨天經過隊友不厭其煩特別耐心的給我講解了這個問題的思路以及解決方案之後感覺豁然開朗啊!
這個問題應用了深搜,回溯的思想,第一個是很好放的,後面的就得慢慢來的,後面若碰到了不能放的就調整上一層,直到全部搜完。*-*
下面是我理解這個問題的代碼,僅用於理解:
#include<iostream>#include<string.h>int tot,c[20],n;void search(int cur)//cur控制行{int i,j;if(cur==n)tot++;elsefor(i=0;i<n;i++){int ok=1;c[cur]=i;//i控制列;for(j=0;j<cur;j++)if(c[cur]==c[j]||cur-c[cur]==j-c[j]||cur+c[cur]==j+c[j])//判斷行列,左右對角是否符合條件;{ok=0;break;}//不合格跳出到i++;if(ok)search(cur+1);}}int main(){while(scanf("%d",&n)!=EOF){if(n==0)break; tot=0; search(0);//從0行開始搜尋。 printf("%d\n",tot);}return 0;}這個代碼提交的時候時間不合格,要打表。。。
AC代碼如下:
#include<iostream>#include<cstring>using namespace std;int vis[20][20],w[12];int n,tot;void dfs(int x){ int i; if(x == n) tot++; else{ for(i=0;i<n;i++){ if(!vis[0][i] && !vis[1][x+i] && !vis[2][x-i+n])//不同行列對角;{ vis[0][i]=vis[1][x+i]=vis[2][x-i+n]=1;//修改全域變數; dfs(x+1); vis[0][i]=vis[1][x+i]=vis[2][x-i+n]=0;//改回來; } } } }int main(){ int j,a; for(j=1;j<=10;j++)//打表,控制在1到10;{ tot=0; memset(vis,0,sizeof(vis)); n=j; dfs(0); w[j]=tot; } while(scanf("%d",&a) && a){ printf("%d\n",w[a]); } return 0;}