zoukankan      html  css  js  c++  java
  • 位运算的魅力---N皇后问题

    题目描述

    有一个N*N的棋盘,有些格子可以放置皇后,一个皇后可以对它这一行的位置,这一列的位置,它所在的左对角线和右对角线攻击,这些位置不能放置皇后,一共放置N个皇后,问有多少种放置的方式。

    输入输出格式

    输入格式:

    第一行有一个N。接下来有N行N列描述一个棋盘,“*”表示可放“.”表示不可放。

    输出格式:

    输出方案总数

    solution

     这道题主要考察位运算,例如101001表示这一排第2、4、5个位置可以放置皇后。

    我们用k进制(这里是二进制)来存储状态,这也是状态压缩的基本思想。

    显然每行只能放置一个皇后,我们逐行枚举

     那么我们需要记录四个状态,一是这一行题目给定的状态,二是这一行中有哪些列会被之前摆放的皇后攻击,那么无法再摆放,三是左对角线的影响,四是右对角线的影响,这些状态只用每行一个数字的二进制来存储就行了。

    判断时将这四种情况取并集,再取反,1的位置就成了可以放置的位置,利用lowbit进行DFS即可,具体的实现细节还要看代码

    code

    #include<cstdio>
    #include<iostream>
    #include<string>
    #define re register
    using namespace std;
    int n,all,sta[50],ans;
    string s;
    int lowbit(int x)//找到最右边的1位 
    {
        return x&-x;
    } 
    //取反是补码,与反码不同 ~(3)=-4;
    void dfs(int now,int L,int R,int d)
    {
        if(now==all){ans++;return;} 
        //当now==all的时候,说明全部摆放完毕,ans++ 
        //now表示到这一行的摆放情况,L表示左对角线的情况
        //R表示右对角线的情况,d记录现在在哪一行,
        //sta[d]表示第d行题目的限制条件 
        int pos=all&(~(now|L|R|sta[d])),p; //all是用来限制,把右对角线左移移出去的除掉 
        while(pos)//枚举每个可以放的位置 
        {
            p=lowbit(pos);
            pos-=p;//这一个位置即将枚举,删掉 
            dfs(now+p,(L+p)>>1,(R+p)<<1,d+1);//左对角线对下一行的影响是它的左下角,因此二进制右移
            //右对角线相反,别忘了加上p处放置的棋子的影响 
        }
    }
    int main()
    {
        scanf("%d",&n);
        all=(1<<n)-1;//表示最终状态,比如 n=4 01111 
        for(re int i=1;i<=n;++i)
        {
            cin>>s;
            for(int j=1;j<=n;++j)
             if(s[j-1]=='.')sta[i]|=(1<<(n-j));//对这个数二进制每个位置进行操作 
        }
        dfs(0,0,0,1);//一开始没放,没有任何摆放过皇后限制 
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    Head First设计模式之观察者模式
    Head First设计模式之策略模式
    EF使用Fluent API配置映射关系
    js判断空字符串、null、undefined、空格、中文空格
    从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值
    System.Data.SqlClient.SqlException: 数据类型 text 和 varchar 在 equal to 运算符中不兼容。
    Content-Type的几种常用数据编码格式
    如何通过Git GUI将自己本地的项目上传至Github
    微信小程序开发之模板
    获取图片的EXIF信息
  • 原文地址:https://www.cnblogs.com/Liuz8848/p/10796167.html
Copyright © 2011-2022 走看看