n皇后2进制算法

来源:互联网 发布:店铺淘宝客还能做吗 编辑:程序博客网 时间:2024/05/22 10:58

杭电的n皇后用测试数据比较多所以不打表就会超时,其实它的其他原理也没什么,就是一个dfs,不断的模拟棋子在棋盘上摆放的情况罢了,用一个二维数组就可以完成了,不过在这里我用类二进制的方法来计算这个问题,就是1代表放了棋子,0代表没放,所以用二进制可以直接模拟,当有一行都为1则是1<<n-1的值时,表示改行已经放慢,不用再遍历,这样要比直接拿数组来模拟来的方便,当在一行中方了一个棋子,这样对接下来每行都进行遍历摆放不能放棋子的位置,用左右移和或运算就可以完成。对某个位置是否放了棋子用&运算来判断。接下来就看下代码:

#include<iostream>
#include<string.h>

using namespace std;

#define N 15

int f[N];
int l[N],r[N],m[N];
int CNT;

void closed(int row,int n,int len)//对摆放好棋子后产生的对其他位置影响进行遍历
{
 int i,temp;

 for (i=row;i<=n;i++)
 {
  temp = l[i-1]<<1;
  if (temp<len)
   l[i] = temp;
  else
   l[i] = 0;
  if (r[i-1]!=1 && r[i-1]!=0)
   r[i] = r[i-1]>>1;
  else
   r[i] = 0;

  m[i] = m[i-1];
  f[i] = f[i] | l[i] | r[i] | m[i];
 }
}

void dfs(int row,int n,int len)
{
 int i,temp;
 int flag=0;
 int tempf[N];

 if (f[row]==len-1)//判断该行是否能放棋子
  return ;

 for (i=0;i<n;i++)
 {
  temp = 1<<i;// 该棋子要放在该行的位置
  
  if ((f[row]&temp) ==0)// 判断该位置是否有棋子
  {
   if (row==n)//是否为最后一行
   {
    CNT ++;
    continue;
   }
   memcpy(tempf,f,sizeof(f));
   l[row] = r[row] = m[row] = temp;
   f[row] = f[row] | temp;
   closed(row+1,n,len);
   
   dfs(row+1,n,len);
   
   memcpy(f,tempf,sizeof(tempf));
  } 
 }
 
}

int main()
{
 int n,len;
 int res[N];

 for (n=1;n<=10;n++)
 { 
  len = 1<<n;
  CNT = 0;
  memset(f,0,sizeof(f));
  memset(l,0,sizeof(l));
  memset(r,0,sizeof(r));
  memset(m,0,sizeof(m));

  dfs(1,n,len);

  res[n] = CNT;
  
 }
 while (cin >> n && n!=0)
  cout << res[n] << endl;

 return 0;
}