例題1:百練 2754
描述
會下國際象棋的人都很清楚:皇後可以在橫、豎、斜線上不限步數地吃掉其他棋子。如何将8個皇後放在棋盤上(有8 * 8個方格),使它們誰也不能被吃掉!這就是著名的八皇後問題。對于某個滿足要求的8皇後的擺放方法,定義一個皇後串a與之對應,即a=b1b2...b8,其中bi為相應擺法中第i行皇後所處的列數。已經知道8皇後問題一共有92組解(即92個不同的皇後串)。給出一個數b,要求輸出第b個串。串的比較是這樣的:皇後串x置于皇後串y之前,當且僅當将x視為整數時比y小。
輸入
第1行是測試資料的組數n,後面跟着n行輸入。每組測試資料占1行,包括一個正整數b(1 <= b <= 92)
- 輸出
- 輸出有n行,每行輸出對應一個輸入。輸出應是一個正整數,是對應于b的皇後串。 樣例輸入
-
2 1 92
樣例輸出 -
15863724 84136275
分析:主要是滿足條件分析:
其中A[cur]==A[j]是判斷皇後是否會縱向攻擊:
其中cur-A[cur]==j-A[j]||cur+A[cur]==j+A[j]語句的意思是:皇後(cur,A[cur])和皇後(j,A[j])是否在同一對角線上:
判斷的原理如圖所示:
1 | 2 | 3 | 4 | 5 | 6 | 7 |
-1 | 1 | 2 | 3 | 4 | 5 | 6 |
-2 | -1 | 1 | 2 | 3 | 4 | 5 |
-3 | -2 | -1 | 1 | 2 | 3 | 4 |
-4 | -3 | -2 | -1 | 1 | 2 | 3 |
-5 | -4 | -3 | -2 | -1 | 1 | 2 |
-6 | -5 | -4 | -3 | -2 | -1 | 1 |
-7 | -6 | -5 | -4 | -3 | -2 | -1 |
(a) 格子(x,y)的y-x值标志了主對角線
1 | 2 | 3 | 4 | 5 | 6 | 7 | |
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
(b)格子(x,y)的y+x值标志了副對角線
用x表示行,y表示列,則有x1=cur,y1=A[cur]:X2=j;y2=A[j];
根據圖中的數值關系,可知在同一主對角線滿足:cur-A[cur]==j-A[j];在同一副對角線滿足:cur+A[cur]==j+A[j]
#include<iostream>
using namespace std;
int A[10],num=1,B[100][10];
int DFS(int cur)
{ if(cur==8)
{ for(int i=0;i<8;i++)
B[num][i]=A[i];
num++;
}
else
for(int i=0;i<8;i++)
{ int flag=1;
A[cur]=i+1;
for(int j=0;j<cur;j++)
if(A[cur]==A[j]||cur-A[cur]==j-A[j]||cur+A[cur]==j+A[j]) {flag=0;break;}
if(flag) DFS(cur+1);
}
}
int main()
{ int n,m;
cin>>n;
DFS(0);
while(n--)
{ cin>>m;
for(int i=0;i<8;i++)
cout<<B[m][i];
cout<<endl;
}
return 0;
}
題2:Tyvj 1080(N皇後),需要剪枝利用use[2][]直接判斷目前的皇後所在列和兩個對角線是否有其他的皇後,注意主對角線标志y-x可能為負,是以存儲的時候要+n。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAX=15;
#define CLR(arr,val) memset(arr,val,sizeof(arr))
int n,sum,A[MAX],use[MAX][2*MAX];
void DFS(int cur)
{ if(cur==n)
{ sum++;
if(sum<=3)
{ for(int i=0;i<n;i++)
printf("%d ",A[i]);
printf("\n");
}
}
else
{ for(int i=0;i<n;i++)
if(!use[0][i]&&!use[1][cur+i]&&!use[2][cur-i+n])//use[0][i]判讀目前皇後所在列是否存在其它皇後
{ A[cur]=i+1;
use[0][i]=use[1][cur+i]=use[2][cur-i+n]=1; //used[1][cur+i]為副對角線
DFS(cur+1);
use[0][i]=use[1][cur+i]=use[2][cur-i+n]=0; //use[2][cur-i+n]為主對角線
}
}
}
int main()
{ while(scanf("%d",&n)!=EOF)
{ sum=0;
DFS(0);
CLR(use,0);
printf("%d\n",sum);
}
return 0;
}