hdu2553N皇后问题

来源:互联网 发布:jsp购物系统源码 编辑:程序博客网 时间:2024/05/24 03:20

N皇后问题

打表 

 #include<iostream> using namespace std; int a[11]={0,1,0,0,2,10,4,40,92,352,724}; int main() {     int n;     while(scanf("%d",&n)>0&&n)     {         printf("%d\n",a[n]);     }     return 0; }


/************************************************************ * Author        : rudolf * Last modified : 2013-04-23 15:27 * Filename      : caogao.cpp * Description   : * *********************************************************/#include <stdio.h>#include <iostream>#include<string.h>using namespace std;int map[20],a[20],hang[20],n,cnt;void DFS(int num){int i,j,flag;if(num==n+1)//到n也成立了才会搜索n+1{cnt++;return;}for(i=1;i<=n;i++)if(!hang[i])//不在同一行{flag=1;map[num]=i;//第num列第i行放第num个皇后for(j=1;j<num;j++)if((map[num]-num==map[j]-j)||(map[num]+num==map[j]+j))//判断是否在对角线上{flag=0;break;}if(flag){hang[i]=1;DFS(num+1);//递归调用hang[i]=0;//回溯}}}int main(){int i,m;for(i=1;i<11;i++)//打表列出N个皇后对应几种方法{memset(map,0,sizeof(map));memset(hang,0,sizeof(hang));n=i;cnt=0;DFS(1);a[i]=cnt;}while(cin>>m&&m!=0)cout<<a[m]<<endl;return 0;}


/**n皇后问题,由于N 是小于等于10的正整数,所以可以使用打表的方法把前十中情况全部找出来存起来然后每次输入时不用重新的计算了。*/#include <stdio.h>#define NUMS 10/*输入的数字1---10*/int N;/*棋盘*/int chessboard[11][11];/* 用来记录拜访数目 */int cal;/*检查皇后放置此行此列是否可以,可以返回1,不可以返回0此递归是一行一行找的,K是棋盘的长度*/int dfs_check(int row,int column,int k){    /* 说明已经到了棋盘的界外,前边都符合了 */    if(row>k)    {        cal++;        return 1;    }    /* 正上方是否有皇后*/    for(int i = 1; i < row; i++)        /* 如果有皇后则返回不能放置这里返回0*/    if(chessboard[i][column] == 1)    return 0;    /* 左右上方45度角检查是否可以*/    /* 左上方*/    for(int i=row-1,j=column-1;i>0&&j>0;i--,j--)    if(chessboard[i][j] == 1)    return 0;    /* 右上方*/    for(int i=row-1,j=column+1;i>0&&j<=k;i--,j++)    if(chessboard[i][j] == 1)    return 0;    /*标记这个位置成功了*/    chessboard[row][column] = 1;    /*进行下一行搜索*/    for(int i=1;i<=k;i++)    if(dfs_check(row+1,i,k)==1)    break;    chessboard[row][column] = 0;    return 0;}int main(){    int i,j,k;    int count[11];    /*打表*/    for(k=1;k<=NUMS;k++)    {        count[k] = 0;        cal = 0;        /*首先将棋盘初始化全部置为0*/        for(i=0;i<=NUMS;i++)        for(j=0;j<=NUMS;j++)        chessboard[i][j]=0;        for(i=1;i<=k;i++)        dfs_check(1,i,k);        count[k] = cal;    }    while(scanf("%d",&N)!=EOF&&N!=0)    printf("%d\n",count[N]);    return 0;}



回溯法(转)能力有限,理解不了他的代码http://blog.csdn.net/alongela/article/details/6755770

用回溯法就可以解决,设皇后的编号依次为1,2,……,n,则可以认为第i个皇后必须摆放在第i行,然后枚举第一个皇后的位置进行回溯,若某一次发现某个皇后无法找到摆放位置则直接返回,如果所有皇后都可以找到摆放位置,则说明存在一种摆法满足要求,统计有多少种摆法即可。


此题n<=10,测试数据中会有大量重复数据,因此要保存答案,遇到曾经计算过的n直接输出即可,否则可能会超时。

#include<iostream>using namespace std;int n;int x[100];int ans[11];bool Place(int k){int i = 1;while (i<k){if (x[i]==x[k] || abs(x[i]-x[k])==abs(i-k))return false;i++;}return true;}int main(){int k, cnt;memset(ans, 0, sizeof(ans));while (scanf("%d", &n)!=EOF && n!=0){if (ans[n]>0) {printf("%d\n", ans[n]);continue;}x[1] = 0;k = 1, cnt = 0;while (k>0){x[k]++;while (x[k]<=n && !Place(k)){x[k]++;}if (x[k]<=n){if (k==n){cnt++;}else {k++;x[k] = 0;}}else k--;}ans[n] = cnt;printf("%d\n", cnt);}return 0;}

dfs

#include<iostream> #include<math.h> using namespace std; int s[12][12],n,count; int panduan(int h,int l) {     for(int i=0;i<n;i++)           //判断列     {         if(s[i][l]==0||i==h)             continue;         else             return 0;     }     for(i=0;i<n;i++)            //判断行     {         if(s[h][i]==0||i==l)             continue;         else             return 0;     }     for(i=0;i<n;i++)          //判断成45度的线     {         for(int j=0;j<n;j++)         {             if(s[i][j]==0||(i==h&&j==l))                 continue;             else             {                 if(abs(h-i)==abs(l-j))          //只要y=kx+b中abs(k)==1,说明成了45度的线                     return 0;             }         }     }     return 1; } void dfs(int num,int f) {     int i,j;     if(num==n*n)     {         if(f==0)             count++;         return;     }     if(num>n*n)return;     i=num/n;     j=num%n;     if(s[i][j]==0&&panduan(i,j))     {         s[i][j]=1;         dfs(num+1,f-1);         s[i][j]=0;     }     dfs(num+1,f); } int main() {     while(scanf("%d",&n)>0&&n)     {         memset(s,0,sizeof(s));         count=0;         dfs(0,n);         //printf("\n\n");         printf("%d\n",count);     }     return 0; }