zoukankan      html  css  js  c++  java
  • [ An Ac a Day ^_^ ] POJ 3254 Corn Fields 状压dp

    题意:

    有一块n*m的土地

    0代表不肥沃不可以放牛 1代表肥沃可以放牛

    且相邻的草地不能同时放牛

    问最多有多少种放牛的方法并对1e8取模

    思路:

    典型的状压dp 能状态压缩 能状态转移

    能状态压缩的题的特点就是只有两种状态

    所以用0 1表示两种状态 用位运算判断是否符合条件

    然后将前一行的合理状态转移到后一行

    最后统计最后一行的状态

    dp[i][j]代表第i行以第j种状态放牛时有多少种不同的状态

    (c++的语言特性是 封装 继承 多态~) 

     1 /* ***********************************************
     2 Author        :Sun Yuefeng
     3 Created Time  :2016/10/31 17:59:53
     4 File Name     :C.cpp
     5 ************************************************ */
     6 
     7 #include<cstdio>
     8 #include<iostream>
     9 #include<algorithm>
    10 #include<cmath>
    11 #include<cstring>
    12 #include<string>
    13 #include<bitset>
    14 #include<map>
    15 #include<set>
    16 #include<stack>
    17 #include<vector>
    18 #include<queue>
    19 #include<list>
    20 #define M(a,b) memset(a,b,sizeof(a))
    21 using namespace std;
    22 typedef long long ll;
    23 const int inf=0x3f3f3f3f;
    24 const int maxn=1<<15;
    25 const int mod=1e8;
    26 int dx[8]= {0,0,1,-1,1,-1,1,-1};
    27 int dy[8]= {1,-1,0,0,-1,1,1,-1};
    28 
    29 int _map[maxn]; //记录给出的每块地的状态
    30 int st[maxn]; //记录每一行的状态
    31 int dp[15][maxn];
    32 
    33 bool judge(int x) //判断相邻两位是否同时为1
    34 {
    35     return (x&(x<<1));
    36 }
    37 
    38 bool judge(int x,int y) //判断两位是否同时为1
    39 {
    40     return _map[x]&st[y];
    41 }
    42 
    43 int main()
    44 {
    45     //freopen("in.txt","r",stdin);
    46     //freopen("out.txt","w",stdout);
    47        int n,m;
    48     while(cin>>n>>m){
    49         int x;
    50         M(dp,0),M(_map,0),M(st,0);
    51         for(int i=0;i<n;i++)
    52         {
    53             for(int j=0;j<m;j++)
    54             {
    55                 cin>>x;
    56                 if(!x)
    57                 {
    58                     _map[i]+=(1<<j); //向图中添加空地
    59                 }
    60             }
    61         }
    62         int k=0;
    63         for(int i=0;i<(1<<m);i++) //初始化能不能以i状态放牛
    64         {
    65             if(!judge(i))
    66             {
    67                 st[k++]=i;
    68             }
    69         }
    70         for(int i=0;i<k;i++) //初始化第一行状态
    71         {
    72             dp[0][i]=(!judge(0,i));
    73         }
    74         for(int i=1;i<n;i++)
    75         {
    76             for(int j=0;j<k;j++)
    77             {
    78                 if(judge(i,j)) continue; //判断第i行是否能以j的方式放牛
    79                 for(int l=0;l<k;l++)
    80                 {
    81                     if(judge(i-1,l)) continue; //判断上一行状态
    82                     if(!(st[j]&st[l])) //符合题意转移状态
    83                         dp[i][j]+=dp[i-1][l];
    84                 }
    85             }
    86         }
    87         int ans=0;
    88         for(int i=0;i<k;i++)
    89         {
    90             ans+=dp[n-1][i];
    91             ans%=mod;
    92         }
    93         cout<<ans<<endl;
    94     }    
    95     return 0;
    96 }
  • 相关阅读:
    用Python计算最长公共子序列和最长公共子串
    两个有序数列,求中间值 Median of Two Sorted Arrays
    python判断平衡二叉树
    经验之谈:如何为你的机器学习问题选择合适的算法?
    跑道没了,它们还在跑:澳门赛狗业的遗孤
    钉钉:工作的归工作,生活的…也归工作?
    假·照骗,真·社交焦虑
    苹果市值破万亿,iPhone 会涨价吗?
    写日志(log)
    多维数组排序
  • 原文地址:https://www.cnblogs.com/general10/p/6016956.html
Copyright © 2011-2022 走看看