N皇后问题(总结性)

来源:互联网 发布:淘宝卖龙年限定 编辑:程序博客网 时间:2024/06/06 15:03

在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。

Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
Sample Input
1850
Sample Output
19210


很经典的n皇后问题。

第一个我放的代码是很经典而又简练的代码,但是放在vj上是超时,但是依然是通过回溯法做出来的

个人认为很巧妙

首先,进去函数后进行dfs对n皇后的竖坐标进行挨个位置枚举,x【i】=j也就是对坐标的标记,即第i行的竖坐标为j,然后对i ,j判断这个位置的可行性,枚举之间的已经确定好的数据即x[0]到x[i-1]所以的竖坐标值都不相同,且不再同一斜线,即相对应的的x的差值和相对应的的y的差值不同(斜线问题,仔细思考,也就是

abs(k-i)==abs(x[i]-x[k])很重要
)如果ij可能,进入下一行进行枚举

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#define maxx 12using namespace std;int sum=0,n;int x[maxx];int judge(int k)//判断x[k]列k行是否合理{    int i;    for(i=1;i<k;i++)    {        if(x[i]==x[k]||abs(k-i)==abs(x[i]-x[k]))        {            return 0;        }    }    return 1;}int queen(int t){    if(t>n)//合适+1(可行解)        sum++;    else    {        for(int i=1;i<=n;i++)        {            x[t]=i;//t行i列            if(judge(t))            {                queen(t+1);            }        }    }    return sum;}int main(){    int t;    while(~scanf("%d",&n))    {        memset(x,0,sizeof(x));        sum=0;        if(n==0)            break;        else            t=queen(1);        printf("%d\n",t);    }    return 0;}

后来发现就是要把数据存入数组就可以解决超时问题,要注意,数据较小时,把数据答案存入数组,时间会减少不少
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>using namespace std;int book[15];int cnt;int judge(int k){    int i;    for(i=1;i<k;i++)    {        if(book[i]==book[k]||abs(i-k)==abs(book[i]-book[k]))        {            return 0;        }    }    return 1;}void dfs(int k,int n){    if(k>n)    {        cnt++;    }    else    {        for(int i=1;i<=n;i++)        {            book[k]=i;            if(judge(k))            {                dfs(k+1,n);            }        }    }}int main(){    int ans[12],t;    for(int i=1;i<=10;i++)    {        memset(book,0,sizeof(book));        cnt=0;        dfs(1,i);        ans[i]=cnt;    }    while(~scanf("%d",&t))    {        if(t==0)            break;        else        {            printf("%d\n",ans[t]);        }    }    return 0;}

第二种方法,简单的dfs,标记较多但是时间复杂度比较小
#include <stdio.h>#include <stdlib.h>#include <string.h>int book_x[15],book_y[15],book_z[15];int count;int judge(int i,int step){    int k;    for(k=step-1;k>=1;k--)    {        if(book_y[k]==i+step)            return 0;        if(book_z[k]==i-step)            return 0;    }    book_y[step]=i+step;    book_z[step]=i-step;    return 1;}void dfs(int step,int sum){    int i;    if(step==sum+1)    {        count++;        return;    }    for(i=1;i<=sum;i++)    {        if(book_x[i]==0&&judge(i,step)==1)        {            book_x[i]=1;            dfs(step+1,sum);            book_x[i]=0;        }    }}int main(){    int ans[15];    int i,n;    for(i=1;i<=10;i++)    {        count=0;        memset(book_x,0,sizeof(book_x));        memset(book_y,0,sizeof(book_y));        memset(book_z,0,sizeof(book_z));        dfs(1,i);        ans[i]=count;    }    while(~scanf("%d",&n))    {        if(n==0)            break;        printf("%d\n",ans[n]);    }    return 0;}


0 0