• Luogu P1879 [USACO06NOV]玉米田Corn Fields 【状压dp模板】


    gate

    前置知识

    位运算常用方法

    判断一个数字x二进制下第i位是不是1

    • return ((1<<(i1))&x)?true:false

    将一个数字x二进制下第i位更改成1。

    • x=x|(1<<(i1))

    把一个数字二进制下最靠右的第一个1去掉。

    • x=x&(x1)

    判断一个数是否为2的幂

    • return x & (x-1) == 0 

    找到最右边的1(也就是lowbit)

    • return x & (-x)

    直接看代码

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    #define MogeKo qwq
    using namespace std;
    
    const int mod = 1e9;
    
    int n,m,x,ans;
    int a[13],f[13][1<<12+5],g[1<<12+5];
    
    int main() {
        scanf("%d%d",&m,&n);
        for(int i = 1; i <= m; i++)
            for(int j = 1; j <= n; j++) {
                scanf("%d",&x);
                a[i] = (a[i]<<1)|x;
            }
    
        for(int i = 0; i < (1<<n); i++)
            g[i] = (!((i<<1)&i) && !((i>>1)&i));
            
        f[0][0] = 1;
        for(int i = 1; i <= m; i++)
            for(int j = 0; j < (1<<n); j++)
            if(g[j] && ((j&a[i]) == j))
                for(int k = 0; k < (1<<n); k++)
                if((k & j) == 0)
                        f[i][j] = (f[i][j] + f[i-1][k])%mod;
        for(int i = 0; i < (1<<n); i++)
            ans = (ans + f[m][i])%mod;
        printf("%d
    ",ans);
        return 0;
    }

     

    限制条件:

    1. 土地本身可用
    2. 左右不相邻
    3. 上下不相邻

    首先读入每一格土地状态,对于第i行,用a[i]表示每一块土地是否可用;

    a[i]用一个二进制数,每读一个,将原来的a[i]左移一位,并加上当前的一位。

    显然,对于一行n列的土地,这一行的状态一共有(1<<n)种(比如000,001,010,011,100,101,110,111)

    那么,从0枚举到(1<<n)-1,就能枚举到每一种情况。

    如何判断是否左右相邻?如果一个状态是左右不相邻的,那将它像左(或右)移一位后,一定是交错的,也就是说没有移动前后都为1的数位。比如,

    01001

    10010

    所以,对于每一个状态i,分别判断i&(i<1)和i&(i>>1)是否都为0,是则合法,g[i] = 1.

    如何判断上下相邻?

    枚举每一行i及状态j。

    如果状态j合法,必须有则g[j]==1,且在j中不能包含不可用的土地。

    也就是说,j中包含的每一块土地,都包含在这一列的合法的集合a[i]中,即(j&a[i]) == j.

    枚举上一行的状态k。

    k,j不能存在上下相邻的土地,即(k&j)==0.

    将上一行的状态k加入这一行的状态j中,即f[i][j] += f[i-1][k].

    最后得到了最后一行每种状态下的方案数,累加即可。

    注意:初始化f[0][0] = 1

    
    
  • 相关阅读:
    48. Rotate Image
    47. Permutations II
    46. Permutations
    45. Jump Game II
    44. Wildcard Matching
    43. Multiply Strings
    42. Trapping Rain Water
    Python_匿名函数
    Python_内置函数之map()
    Python_面向对象_单例模式
  • 原文地址:https://www.cnblogs.com/mogeko/p/11552238.html
Copyright © 2020-2023  润新知