• 【洛谷题解/AcWing题解/SCOI2005】P1896/AcWing1064 互不侵犯


    原题链接:
    洛谷:https://www.luogu.com.cn/problem/P1896
    AcWing:https://www.acwing.com/problem/content/description/1066/
    难度:提高+/省选-(…)
    涉及知识点:状态压缩DP

    分析与解决

    非常经典的状态压缩DP问题。定义 f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k] 为摆完前 i i i 行,摆了 j j j 个国王,状态为 k k k 的集合。考虑状态压缩,即用二进制数表示某一行的状态,例如全是 0 的话就是一个国王也没有摆,反之就是全部都摆了(当然这是不合法的状态)。由于题目给出了条件限制,我们就需要考虑当前的状态转移是不是合法的,怎样判定呢?如下两点:

    • 相邻两行的某一列不能同时为 1。如果同时为 1 上下就要打起来了。
    • 某一行的相邻两列不能同时为 1,否则左右就要打起来了。
    • 至于四个角也是某一行的上下左右。

    那么对于上面说的第一、二种情况,可以使用位运算。对于第一种情况,使用与与运算;对于第二种运算,使用或运算后判断状态的合法性(左右有没有冲突)。
    考虑提前预处理在某一行中从 0 ∼ 1 < < n 0\sim 1 << n 01<<n 的所有状态的合法性,因为可能存在某一些状态自身就是不合法的,用一个 v e c t o r vector vector 存储所有的合法状态,还要用一个数组记录当前的状态有多少个国王,以便于后面进行状态转移时在体积层(国王数量)判断是否是超过当前数量限制。
    然后考虑初始的合法状态间能否进行合法的转移,即执行上文中的两个位运算操作,并且用一个 v e c t o r vector vector 记录状态转移的关系。
    最后再状态转移时,枚举每一个状态的可转移状态,判断数量会不会超过,做一下状态转移即可。用 a a a 表示当前状态,用 b b b 表示可转移状态,用 c c c 表示当前状态的国王数量,状态转移方程为:
    f [ i ] [ j ] [ a ] + = f [ i ] [ j − c ] [ b ] f[i][j][a] += f[i][j - c][b] f[i][j][a]+=f[i][jc][b]
    初始化 f [ 0 ] [ 0 ] [ 0 ] = 1 f[0][0][0] = 1 f[0][0][0]=1

    AC代码

    #include 
    #include 
    #include 
    
    using namespace std;
    
    const int N = 12, M = 1 << 10, K = 110;
    
    typedef long long LL;
    int n, m;
    int cnt[M];
    vector<LL> head[M]; //某个状态可以转移过去的状态
    vector<LL> state; //预处理的所有合法状态
    LL f[N][K][M];
    
    //某个状态是否合法
    bool check(int x)
    {
        for (int i = 0; i < n; i++)
        {
            if ((x >> i & 1) && (x >> i + 1 & 1)) return false;
        }
        return true;
    }
    
    //统计某个状态的1的数量也就是这个状态下摆放的国王数量
    int count(int x)
    {
        int res = 0;
        for (int i = 0; i < n; i++) res += x >> i & 1;
        return res;
    }
    
    int main()
    {
        cin >> n >> m;
        for (int i = 0; i < 1 << n; i++)
        {
            //打表
            if (check(i))
            {
                //是个合法状态
                state.push_back(i);
                cnt[i] = count(i); //摆放的国王数量
            }
        }
        
        //检查某个状态能否向另一个状态转移
        for (int i = 0; i < state.size(); i++)
        {
            for (int j = 0; j < state.size(); j++)
            {
                int a = state[i], b = state[j];
                if ((a & b) == 0 && check(a | b))
                {
                    head[i].push_back(j);
                    
                }
            }
        }
        
        f[0][0][0] = 1; //初始化
        for (int i = 1; i <= n +1 ; i++)
        {
            for (int j = 0 ; j <= m; j++)
            {
                for (int a = 0; a < state.size(); a++)
                {
                    for (auto b : head[a])
                    {
                        int c = cnt[state[a]];
                        if (j >= c)
                        {
                            f[i][j][a] += f[i - 1][j - c][b];
                        }
                    }
                }
            }
        }
        
        cout << f[n + 1][m][0];
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
  • 相关阅读:
    Spring Bean细节
    招投标系统软件源码,招投标全流程在线化管理
    MFC Windows 程序设计[130]之页面常用控件组
    P1404 平均数
    嵌入式快速入门学习笔记-Framebuffer
    SpringBoot自定义starter
    给rust的cargo环境或gnome构建器安装rust-analyzer
    北斗高精度组合导航终端
    cdh 6.3.2 离线部署
    Redis是如何做缓存的
  • 原文地址:https://blog.csdn.net/lightningcs/article/details/126441581