• POJ-3254 + POJ-1185 状压DP入门题


    题意:一个n*m的矩阵,0表示不能放,1表示能放,不能有两个1相邻放,问有多少种方案%1e9

    原以为我还比较会位运算的。。。还是太天真了。。。

    状压的各种细节就不写了别的博客讲了很多,重点梳理一下自己的思路

    因为两个1不能出现在相邻位置,首先筛出(1<<m)-1范围内,没有两个1在一起的二进制数,就是所有的可行方案

    然后,状压dp还是dp,核心仍然是如何转移,第一层肯定是行数,第二层就枚举当前可行的方案数,

    如何判断这个方案数在当前行可用呢?输入时先把图上的状态反着存起来,这样刚好可以&一下判断!

    原因在于原本不可用的块反过来存是1,如果你的方案在这个不可用的1上有放置,那么&之后就是非0的,矛盾!

    确定之后来看转移,这里同样要枚举上一层的可能情况,然后验证冲突,这里显然简单&一下

    如果是不冲突的那就直接转移了,求方案数的转移直接加起来取模

    普通DP学的不好开状压还是勉强了。。。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<iostream>
     5 #define LL long long
     6 #define debug(x) cout << "[" << x << "]" << endl
     7 using namespace std;
     8 
     9 const int mod = 1e9;
    10 int dp[15][5000], mp[15], sta[5000];
    11 
    12 int main(){
    13     int m, n, k = 0, x;
    14     scanf("%d%d", &n, &m);
    15     for (int i = 1; i <= n; i++){
    16         for (int j = 1; j <= m; j++){
    17             scanf("%d", &x);
    18             if (!x) mp[i] |= 1<<(j-1);
    19         }
    20     }
    21     for (int i = 0; i < (1<<m); i++)
    22         if (!(i&(i<<1))) sta[k++] = i;
    23     for (int i = 0; i < k; i++)
    24         if (!(sta[i] & mp[1])) dp[1][i] = 1;
    25     for (int i = 2; i <= n; i++){
    26         for (int j = 0; j < k; j++){
    27             if (mp[i] & sta[j]) continue;
    28             for (int s = 0; s < k; s++){
    29                 if (mp[i-1] & sta[s]) continue;
    30                 if (sta[j] & sta[s]) continue;
    31                 dp[i][j] += dp[i-1][s];
    32             }
    33         }
    34     }
    35     int ans = 0;
    36     for (int i = 0; i < k; i++){
    37         ans += dp[n][i];
    38         ans %= mod;
    39     }
    40     printf("%d
    ", ans);
    41     return 0;
    42 }

    UPD:POJ-1185炮兵阵地

    跟这题一样,预处理状态要检查三格里面只能有一个1的,所以合法状态变少了

    然后从预处理第一行变成预处理前两行,所以dp的枚举也多了一维

    都是一个套路

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #define LL long long
     6 #define INF 0x3f3f3f3f
     7 #define debug(x) cout << #x << " = " << x << endl
     8 using namespace std;
     9 
    10 int dp[105][70][70];
    11 int sta[70], mp[105], a[70];
    12 char s[15];
    13 
    14 int main(){    
    15     int n, m;
    16     scanf("%d%d", &n, &m);
    17     for (int i = 1; i <= n; i++){
    18         scanf("%s", s+1);
    19         for (int j = 1; j <= m; j++){
    20             if (s[j] == 'H')
    21                 mp[i] |= (1<<(j-1));
    22         }
    23     }
    24 
    25     int s = 0;
    26     for (int i = 0; i < (1<<m); i++){
    27         if ((i & (i<<1)) || (i & (i<<2))) continue;
    28         sta[s] = i;
    29         int num = 0, k = i;
    30         while (k){
    31             num++;
    32             k &= k-1;
    33         }
    34         a[s++] = num;
    35     }
    36 
    37     for (int i = 0; i < s; i++){
    38         if (mp[1] & sta[i]) continue;
    39         dp[1][i][0] = a[i];
    40     }
    41 
    42     for (int i = 0; i < s; i++){
    43         if (mp[2] & sta[i]) continue;
    44         for (int j = 0; j < s; j++){
    45             if (mp[1] & sta[j]) continue;
    46             if (sta[i] & sta[j]) continue;
    47             dp[2][i][j] = max(dp[2][i][j], dp[1][j][0]+a[i]);
    48         }
    49     }
    50 
    51     for (int i = 3; i <= n; i++){
    52         for (int j = 0; j < s; j++){
    53             if (mp[i] & sta[j]) continue;
    54             for (int k = 0; k < s; k++){
    55                 if (mp[i-1] & sta[k]) continue;
    56                 if (sta[j] & sta[k]) continue;
    57                 for (int r = 0; r < s; r++){
    58                     if (mp[i-2] & sta[r]) continue;
    59                     if (sta[j] & sta[r]) continue;
    60                     if (sta[k] & sta[r]) continue;
    61                     dp[i][j][k] = max(dp[i][j][k], dp[i-1][k][r]+a[j]);
    62                 }
    63             }
    64         }
    65     }
    66 
    67     int ans = 0;
    68     for (int i = 0; i < s; i++)
    69         for (int j = 0; j < s; j++)
    70             ans = max(ans, dp[n][i][j]);
    71     printf("%d
    ", ans);
    72     return 0;
    73 }
    View Code
  • 相关阅读:
    webstorm 取消拖动代码
    可读流
    页面上怎么使用svg
    从element-ui按需引入去探索
    vue组件库用markdown生成文档
    create-react-app中的babel配置探索
    svg 使用中的疑惑点
    express中是如何处理IP的?
    koa中是如何封装获取客户端IP的?
    博客园文章添加目录
  • 原文地址:https://www.cnblogs.com/QAQorz/p/9401649.html
Copyright © 2020-2023  润新知