题目描述
检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。
上面的布局可以用序列2 4 6 1 3 5来描述,第i个数字表示在第i行的相应位置有一个棋子,如下:
行号 1 2 3 4 5 6
列号 2 4 6 1 3 5
这只是跳棋放置的一个解。请编一个程序找出所有跳棋放置的解。并把它们以上面的序列方法输出。解按字典顺序排列。请输出前3个解。最后一行是解的总个数。
输入输出格式
输入格式:
一个数字N (6 <= N <= 13) 表示棋盘是N x N大小的。
输出格式:
前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。
样例输入:
6
样例输出:
2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4
解题思路 :
这个题每行必放一个皇后,从第一行的某个位置开始放一个皇后后,其他行的皇后的位置也就确定了,要么能放下总皇后的个数,要么不能放所需要放的总皇后个数,所以我只需要改变第一行皇后的位置,接下的 n-1 行,进行DFS搜索,能满足的条件的位置就暂时放一个皇后,如果后面的皇后满足不了,就回溯到上一步,换一个满足条件的位置放皇后,就这样,我刚刚开始学习,所以最后一个数据会超时,不喜勿喷。
#include <stdio.h>
#include <string.h>
int a[14]; /*标记列是否被皇后占了*/
int b[14][14]; // 标记皇后的的位置
int n;
int sum,zonSum;
int zd(int x,int y){ // 判断该位置对角线是否有皇后
int falge=0;
int x1,y1,x2,y2,x3,y3,x4,y4;
x1=x2=x3=x4=x;
y1=y2=y3=y4=y;
while(1)
{
++x1;
++y1;
if(x1<1||x1>n||y1<1||y1>n)break;
if(b[x1][y1]==-1)
{
falge=1;
break;
}
}
if(falge) return 0;
while(1)
{
--x2;
--y2;
if(x2<1||x2>n||y2<1||y2>n) break;
if(b[x2][y2]==-1)
{
falge=1;
break;
}
}
if(falge) return 0;
while(1)
{
--x3;
++y3;
if(x3<1||x3>n||y3<1||y3>n) break;
if(b[x3][y3]==-1)
{
falge=1;
break;
}
}
if(falge) return 0;
while(1)
{
++x4;
--y4;
if(x4<1||x4>n||y4<1||y4>n) break;
if(b[x4][y4]==-1)
{
falge=1;
break;
}
}
if(falge) return 0;
return 1;
}
void show(){ // 显示皇后的在棋盘的位置
int j,k;
for(j=1;j<=n;j++)
{
for(k=1;k<=n;k++)
{
if(b[j][k]==-1) printf("%d ",k);
}
}
printf("\n");
}
void DFS (int x,int y){
if(sum==n) //如果已放置的皇后和需要放置的皇后相等 就说明放置成功
{
++zonSum;
if(zonSum<=3)show();
return;
}
if(x<1||x>n||y<1||y>n)return ;
int i;
for(i=1;i<=n;i++)
{
if(a[i]!=-1&&zd(x,i))
{
++sum; // 已放置皇后的总数
a[i]=-1; //标记 列
b[x][i]=-1; // 标记皇后的位置
DFS(x+1,1); // 下一行寻找皇后的位置
b[x][i]=0; // 回溯
a[i]=0; //回溯
--sum; //回溯
}
}
return ;
}
int main(){
int i;
zonSum=0;
scanf("%d",&n);
for(i=1;i<=n;i++) //在第一行上从第一个位置开始放置皇后
{
sum=1;
a[i]=-1;
b[1][i]=-1;
DFS(2,1);
memset(b,0,sizeof(b));
memset(a,0,sizeof(a));
}
printf("%d",zonSum);
return 0;
}