题目:N皇后加强版

题目描述

经典问题。
N皇后问题(加强版)

皇后们想知道自己到底有多少种排列方式。

国际象棋中规定:
皇后对角线互能攻击。
有两个皇后位于同一行或者同一列都不符合要求。!

也就是说,把N个棋子被放置在棋盘上,使得每行、每列只有一个,每条对角线(包括两条主对角线的所有对角线)上至多有一个棋子

下面给出一个例子
列号
1 2 3 4 5 6
-------------------------
1 | | O | | | | |
-------------------------
2 | | | | O | | |
-------------------------
3 | | | | | | O |
-------------------------
4 | O | | | | | |
-------------------------
5 | | | O | | | |
-------------------------
6 | | | | | O | |
-------------------------
'O'表示皇后,
这样是一个符合要求的方法。
其中,上面的布局可以用序列2 4 6 1 3 5来描述,第i个数字表示在第i行的相应位置有一个棋子,如下:
行号 1 2 3 4 5 6
列号 2 4 6 1 3 5

我们要求的就是输出方案每个皇后的列号!


输出: 前3种排列方案,
共有多少种排列方案!!

输入格式

读入N,其中(4<=N<=13).
表示棋盘是N x N.

输出格式

前3行为N皇后的前3种排列。用空格隔开。
(若不足3种全部输出)
第4行为共有多少种排列。

 

 

 

 

题解:———————————————————————————————————————————————————

知道这道题是USACO里面的,就格外认真对待了,花了5个多小时,并且看了别人的代码才有了一点朦胧的理解,还需钻研。

 

代码实现:

#include<iostream>
using namespace std;

int n,m_n,c[15],total=0;

int print(int x){
    int s = 1;
    while (!(x & 1))
          x >>= 1, s++;
    return s;
     }

void dfs(int row,int ld,int rd,int x){
     if(row==m_n)
     {
      total++;int i;
      if(total<=3) 
      {
      cout<<print(c[1])<<" ";
      for(i=2;i<n;i++)
      cout<<print(c[i] ^ c[i - 1])<<" ";
      cout<<print(c[n] ^ c[n- 1])<<endl;
      }
      return ;
                 }
                 
      int pos=m_n & ~(row|ld|rd),p;
      while(pos>0)
      {
       p=pos&(-pos);
       c[x]=row+p;
       dfs(row+p,(ld+p)<<1,(rd+p)>>1,x+1);
       pos=pos-p; 
                  }   
     }

int main()
{
    cin>>n;
    m_n=(1<<n)-1;
    dfs(0,0,0,1);
    cout<<total;

    return 0;

    } 
posted on 2011-12-31 23:46  怡红公子  阅读(394)  评论(0编辑  收藏  举报