DFS之八皇后

来源:互联网 发布:电视伴音收音机淘宝 编辑:程序博客网 时间:2024/05/16 15:37

题目描述

检查一个如下的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大小的。

输出格式:

前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。

输入输出样例

输入样例#1:
6
输出样例#1:
2 4 6 1 3 53 6 2 5 1 44 1 5 2 6 34
  • 题解
典型的深度搜索+回溯。注意,如果再回溯法中修改了全局变量,一定要在回溯之后修改回来,目的是为了不影响下面的DFS。
两种方法,逐步优化:
方法一:
#include <bits/stdc++.h>using namespace std;const int maxn=1000+100;int n,ans=0,c[maxn];void dfs(int cur){    if(cur==n) ans++;    else for(int i=0;i<n;i++){        int ok=1;        c[cur]=i;        for(int j=0;j<cur;j++)            if(c[j]==i||cur-i==j-c[j]||cur+i==c[j]+j){ok=0;break;}//分别搜索相同列,主对角线和副对角线        if(ok) dfs(cur+1);    }}int main(){    scanf("%d",&n);    dfs(0);    printf("%d\n",ans);    return 0;}

方法二:
#include <bits/stdc++.h>using namespace std;const int maxn=13+10;int ans=0,c[maxn],vis[3][maxn];void dfs(int n,int c[],int cur){  if(cur==n){    ans++;;    if(ans<=3){      for(int i=0;i<n;i++)        printf("%d ",c[i]);      printf("\n");    }  }  else for(int i=0;i<n;i++)      if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n]){        c[cur]=i+1;        vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=1;        dfs(n,c,cur+1);        vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=0;      }}int main(){  // freopen("input.txt","r",stdin);  int n;  memset(vis,0,sizeof(vis));  scanf("%d",&n);  dfs(n,c,0);  printf("%d\n",ans);  return 0;}


原创粉丝点击