回溯法之经典问题->皇后问题

来源:互联网 发布:淘宝培训多久 编辑:程序博客网 时间:2024/06/05 10:53

给出n*n的棋盘,能够多少种不同的放置“皇后”的方法。

//递归实现 HDU 2553 //DFS、#include <bits/stdc++.h>using namespace std;int N, total;int pos[10];//存的是row的编号,通过row自己的下标row可以找到对应的pos[row],因为dfs存的时候是pos[row] = row;从而在下面check()中判断是否是同一列的时候判断pos[j] == col?//因为从第一行开始的dfs不存在处于同一行的情况int check(int row,int col){    for( int j = 0; j < row; j++ )    {        if( pos[j] == col ||             abs(col - pos[j]) == abs(row - j) )            //  两点行距          两点列距            return 0;    }    return 1;}void dfs(int row){    if ( row == N ) total++;//if满足刚好放置n个,则总数++    else    {        for( int i = 0; i < N; i++ )        {            if ( check(row,i) )//如果当前点满足条件             {                pos[row] = i;                 dfs(row+1);                pos[row] = 0;            }        }       }}int main(){    int a[11];    for( N = 1; N < 11; N++)    {        total = 0;        dfs(0);        a[N] = total;    }     while(scanf("%d",&N) && N)    {        memset(pos, 0, sizeof(pos));        printf("%d\n",a[N]);    }    return 0;} 
//非递归实现#include <bits/stdc++.h>#define inf -10000#define Max 11using namespace std;int pos[Max];int a[Max];void init(int N){    int *p;    for( p = pos; p < pos + N; ++p )    {        *p = inf;       } }int check(int row,int col,int N){    for( int j = 0; j < N; j++ )    {        if( pos[j] == col || abs(col - pos[j]) == abs(row - j) )            return 0;    }    return 1;}int queen(int N){    int m = 0;    int i = 0,j = 0;    while( i < N )    {        while( j < N )//对i行的每一列进行探测,看是否可以放置皇后         {            if(check(i,j,N))//该位置可以放置皇后             {                pos[i] = j;//第i行放置皇后                 j = 0;      //第i行放置皇后后,需要将此处清零,从下一行的第0开始逐列探测                 break;            }            else{                ++j;//继续探测下一列             }        }        if( pos[i] == inf )//第i行没有找到         {            if( i == 0 )//回溯到第一行,仍然无法找到放置皇后的位置,则已经找到所有的解                 break;            else      //没有找到可以放皇后的列,这时候进行回溯             {                --i;                j = pos[i] + 1;//把上一行皇后的位置往后移一列                 pos[i] = inf;//把上衣行的皇后位置清除,重新探测                 continue;            }        }        if( i == N - 1 )//最后一行找到一个皇后位置,说明有一个结果 ,打印         {            ++m;//          printf("answer %d :\n",++m);//          print();            //此处还要继续,因为要找N皇后的所有解,所有要对当前解进行清除             j = pos[i] + 1;//从最后一行放置皇后 列数的下一列继续探测             pos[i] = inf;//清除最后一行的皇后位置             continue;        }        ++i;//继续探测下一行     }    return m;}int main(){    for( int i = 1; i < Max; i++)    {        memset(pos,0,sizeof(pos));        init(i);        a[i] = queen(i);    }    int n;    while(scanf("%d",&n) && n)    {        cout<<a[n]<<endl;    }     return 0;}
0 0
原创粉丝点击