• POJ3254Corn Fields(状态压缩DP入门)


    题目链接

    题意:一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,要求两个相邻的方格不能同时放牛,即牛与牛不能相邻。问有多少种放牛方案(一头牛都不放也是一种方案)

    分析:每一行看做一个状态,用一个二进制数来表示,每一行会排出牛和牛相邻的情况;由上一行转移到下一行的条件就是这一行和上一行不会存在1在同一列,也就是与操作后为0,

    状态表示: dp[state][i] 表示 在状态为state情况下第i行可以满足的方案数

    状态转移:DP[state][i] += dp[state'][i - 1] (state & state' == 0)

    状态压缩总结博客

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 using namespace std;
     6 const int Mod = 100000000;
     7 int state[600];
     8 int dp[20][600], cur[20];
     9 int n, m, total, top;
    10 inline bool is_ok(int x)
    11 {
    12     if (x & (x << 1)) // 如果存在相邻的1返回0
    13         return 0;
    14     return 1;
    15 }
    16 void init()
    17 {
    18     top = 0;
    19     total = 1 << n;
    20     for (int i = 0; i < total; i++)  
    21         if(is_ok(i))
    22             state[++top] = i;
    23 }
    24 inline bool fit(int x, int i)
    25 {
    26     if (x & cur[i]) 
    27         return 0;
    28     return 1;
    29 }
    30 int main()
    31 {
    32     while (scanf("%d%d", &m, &n) != EOF)
    33     {
    34         init();
    35         int num;
    36         for(int i = 1; i <= m; i++)
    37         {
    38             cur[i] = 0;
    39             for(int j = 1; j <= n; j++)
    40             {
    41                 scanf("%d", &num);
    42                 if (num == 0)
    43                     cur[i] += (1 << (n - j));
    44 //这里之前不明白为什么num == 0的时候开始计数,把不允许放牧的地方都设为1,而允许放牧的就是0,所以判断当前状态与哪些标准状态匹配时候只需判断 & 之后是否为0,因为只要是非0,一定是不行的,在那一个点下不允许放牧,标准却可以放牧。 当前状态可以放牧,即为0,那么标准状态下,这一个位置放不放都可以,所以标准下0,1都可以
    45             }
    46         }
    47         memset(dp, 0, sizeof(dp));
    48         for (int i = 1; i <= top; i++)
    49         {
    50             if (fit(state[i], 1)) // 先判断第一行的情况,state[1] = 0,这也是可以的
    51                 dp[1][i] = 1;
    52         }
    53 
    54         for (int i = 2; i <= m; i++)
    55         {
    56             for(int k = 1; k <= top; k++) // 判断第 i 行可以由哪些标准状态
    57             {
    58                 if(!fit(state[k], i)) continue;
    59                 for (int j = 1; j <= top; j++)  
    60                 {
    61                     if(!fit(state[j], i - 1)) continue; //选择i-1可以的标准状态
    62                     if (state[k] & state[j]) continue; // 没有列相邻的1
    63                     dp[i][k] += dp[i - 1][j];
    64                     dp[i][k] %= Mod;
    65                 }
    66             }
    67         }
    68         int ans = 0;
    69         for (int i = 1; i <= top; i++)
    70         {
    71             ans += dp[m][i];
    72             ans %= Mod;
    73         }
    74         printf("%d
    ", ans);
    75     }
    76     return 0;
    77 }
    View Code
  • 相关阅读:
    hdu 5045 Contest
    hdu 4068 SanguoSHA
    TSP 旅行商问题(状态压缩dp)
    haoi2015 树上操作
    noi 2015 软件包管理器(树链剖分)
    zjoi2008 树链剖分
    读入优化
    动态规划类型总结
    有关Rujia Liu 动态规划的·一些总结
    输入优化
  • 原文地址:https://www.cnblogs.com/zhaopAC/p/5322630.html
Copyright © 2020-2023  润新知