P1219 [USACO1.5]八皇后 Checker Challenge
1.思路
1.1对角线的表示
首先根据题目的要求,我们可以用一个数组line[13]表示皇后放置的位置 如line[4]=5 则表示第4行第5列放了一个皇后。然后再分别用ud[13],ld[13]表示上,下对角线
看上对角线的图,不难发现处于上对角线的值都是相等的则可以用ud[i+j]
来表示,其中i表示第几行,j表示第几列。
可能还有一点很难理解,为什么ud[i-j]能表示一条对角线,不就是一个单独的坐标吗?
其实很容易想明白了,i
可能代表不同的行,因而j
代表的列也会随之改变,所以就表示了一条对角线。
说完上对角线,下对角线应该也很容易理解吧!
可以表示为ld[i+j]
1.2DFS
说到这里,基本到了最核心的地方。就是标记和回溯
void dfs(int i){//i表示第几行
if(i>n) { print();return;}
else {
for(int j=1;j<=n;j++){
if( !row[j] && !ud[i+j] && !ld[i-j+n] ){//列,上,下对角线没有标记,则可以放皇后
line[i]=j; //第i行第j列放了第i个皇后
row[j]=1;//标记
ud[i+j]=1;
ld[i-j+n]=1;
dfs(i+1);
row[j]=0;//回溯
ud[i+j]=0;
ld[i-j+n]=0;
}
}
}
}
1.3打印
void print(){
sum++;
if(sum<=100){
for(int i=1;i<=n;i++)
printf("%d",line[i]);
printf("\n");
}
else
return ;
}
2.源码
#include<stdio.h>
int n;
int line[13],row[13],ud[100],ld[100];
int sum;
int j;
void print(){
sum++;
if(sum<=100){
for(int i=1;i<=n;i++)
printf("%d",line[i]);
printf("\n");
}
else
return ;
}
void dfs(int i){//i表示第几行
if(i>n) { print();return;}
else {
for(int j=1;j<=n;j++){
if( !row[j] && !ud[i+j] && !ld[i-j+n] ){
line[i]=j;
row[j]=1;
ud[i+j]=1;
ld[i-j+n]=1;
dfs(i+1);
row[j]=0;
ud[i+j]=0;
ld[i-j+n]=0;
}
}
}
}
int main(){
scanf("%d",&n);
dfs(1); //从第一行开始,放皇后
printf("%d",sum);
}