Why so serious? --[NKU]schindlerlee

2010年1月13日星期三.sgu224 k皇后问题的位运算优化

2010年1月13日星期三.sgu224
k皇后问题的位运算优化
这个是基本上学过编程的人都会写过的程序。
但是对于这个NP问题,只能搜索解决。如果写的不好的话很容易超时。
今天在Matrix67的文章中看到了使用位运算的方法,本来我还想用dancing links来
搜一下呢,这个方法太精妙了!
传送门: http://www.matrix67.com/blog/archives/266

我们知道(x&-x)是求x的最低位1,而这个操作是非常快的。
在这个递推过程中,只保存当前行的不可行解,然后利用求反和上边说的求最低位1的方法对当前
行的可行解进行遍历,然后递推求解

不过这个不是n皇后问题,是k皇后,所以还需要对算法进行一些小小的改动。
//http://www.cppblog.com/schindlerlee/
typedef 
long long LL;
const int N = 16;
int n, k;

#define bin(x) (1 << (x))
#define L(x) ((x) << 1)
#define R(x) ((x) >> 1)
#define low(x) ((x) & -(x))

int res = 0, full;
//row代表列的状态,ld代表左对角线,rd代表右对角线,cnt是已经使用的皇后数
//line是已经推到了第几第几行
void dfs(int row, int ld, int rd, int cnt, int line)
{
  
int p, t;
  
if (line < n && cnt < k) {
      t 
= full & ~(row | ld | rd);
      
while (t != 0) {
          p 
= low(t);
          t 
^= p;
          dfs(row 
+ p, L(ld + p), R(rd + p), cnt + 1, line + 1);    //下一行
      }
      dfs(row, L(ld), R(rd), cnt, line 
+ 1);    //此行空
  } else if(cnt == k){
      res
++;
  }

}

int main()
{
  
int i, j;
  scanf(
"%d%d"&n, &k);
  full 
= bin(n) - 1;
  dfs(
00000);
  printf(
"%d\n", res);
  
return 0;
}



posted on 2010-01-13 22:52 schindlerlee 阅读(1398) 评论(0)  编辑 收藏 引用 所属分类: 解题报告


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理