• 洛谷p1879/poj3254 Corn Fields


    看到这个题,又看了看数据规模,立马明白是一道状态压缩dp。

    用 f [ i ][ j ] 表示第 i 行的状态为 j 时,前 i 行的方案总数 ( 状态用二进制表示,1表示放奶牛,0表示不放 ) 。

    用 ok[ i ] 表示状态为 i 时是否合法,用 m[ i ]来储存第 i 行的肥沃土地。

    预处理出每一行的合法状态(即没有两个格子相邻),然后以 每行 为阶段进行转移即可。

    具体在转移时,除了考虑之前 ok 数组所记录的状态是否合法,还需要考虑:

    1.与上一行是否冲突((j & k) == 0)

    2.当前行的奶牛的位置上是否都有草((m[i] | j) == m[i])

    那么不难写出代码。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int mod = 1e8;
     4 const int MAXN = 12 + 1;
     5 
     6 inline int read()
     7 {
     8     static int x;
     9     scanf(" %d", &x);
    10     return x;
    11 }
    12 
    13 int M, N;
    14 bool ok[1 << 13];
    15 int f[13][1 << 13], m[MAXN];
    16 
    17 int main()
    18 {
    19     cin>>M>>N;
    20 
    21     for(int i = 1; i <= M; i++)
    22         for(int j = 0; j < N; j++)
    23             m[i] |= (read() << j);
    24 
    25     bool flag;
    26     for(int i = 0; i < (1 << N); i++)
    27     {
    28         flag = false;
    29         for(int j = 1; j < 13; j++)
    30             if( ((i >> j) & 1) & ( (i >> (j - 1)) & 1) ) flag = true;
    31         ok[i] = (flag == false);
    32     }
    33 
    34     f[0][0] = 1;
    35     for(int i = 1; i <= M; i++)
    36         for(int j = 0; j < (1 << N); j++)
    37         {
    38             if(ok[j] && ((m[i] | j) == m[i]))
    39                 for(int k = 0; k < (1 << N); k++)
    40                     if((j & k) == 0)
    41                         f[i][j] = (f[i - 1][k] + f[i][j]) % mod;
    42         }
    43 
    44     int ans = 0;
    45     for(int i = 0; i < (1 << N); i++)
    46         ans = (ans + f[M][i]) % mod;
    47     cout<<ans<<endl;
    48     return 0;
    49 }
  • 相关阅读:
    Python(条件判断和循环)
    大端还是小端
    c语言程序设计 字符串拷贝拷贝演变与初衷
    内存 匹配串
    多态 C2
    多态 C1
    判断是否存在不合法字符(C++)
    va_start、vsprintf、va_end
    java中instanceof用法
    c++ vector相关
  • 原文地址:https://www.cnblogs.com/wsmrxc/p/9031891.html
Copyright © 2020-2023  润新知