• 睡前小dp-poj3254-状压dp入门


    http://poj.org/problem?id=3254

    从这里学的 http://blog.csdn.net/accry/article/details/6607703

    状压dp的入门题。一片N×M的田地,有的地方可以种玉米,有的地方不可以。种玉米的区块不能相邻。种玉米的求总方案数,不种玉米也是一种方案。

    每一行总共2^N种状态,其中删去有相邻的状态,删除不符合给定条件的状态。保留下最终的所有状态。然后开始dp。

    从上往下,每一行之依赖于上一行。所以从上一行转移过去,把状态数加起来就行了。

    其中几个函数写的比较精妙,结合二进制运算理解一下并不难。

    /*--------------------------------------------------------------------------------------*/
    //        Helica's header 
    //        Second Editions
    //        2015.11.7
    //
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <ctype.h>
    #include <cstdlib>
    #include <cstdio>
    #include <vector>
    #include <string>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <set>
    #include <map>
    
    //debug function for a N*M array 
    #define debug_map(N,M,G) printf("
    ");for(int i=0;i<(N);i++)
    {for(int j=0;j<(M);j++){
    printf("%d",G[i][j]);}printf("
    ");}                
    //debug function for int,float,double,etc.
    #define debug_var(X) cout<<#X"="<<X<<endl;
    /*--------------------------------------------------------------------------------------*/
    using namespace std;
    
    const int MOD = 100000000;
    int N,M,T;
    int dp[20][1000],state[1000],cur[20];
    int cnt;
    bool ok(int x)
    {
        if(x&(x<<1)) return 0;
        return 1;
    }
    
    bool fit(int s,int c)
    {
        if(s&c) return 0;
        return 1;
    }
    
    int main()
    {
        while(~scanf("%d%d",&N,&M))
        {
            for(int i=1;i<=N;i++)
            {
                cur[i] = 0;
                for(int j=1;j<=M;j++)
                {
                    int a;
                    scanf("%d",&a);
                    if(a==0) cur[i] += (1<<(M-j));
                }
            }
            cnt=0;
            for(int i=0;i < 1<<M;i++) if(ok(i))
            {
                state[++cnt] = i;        
            }
    
            memset(dp,0,sizeof dp);
            for(int i=1;i<=cnt;i++) if(fit(state[i],cur[1]))
                dp[1][i] = 1;
    
            for(int i=2;i<=N;i++)
            {
                for(int j=1;j<=cnt;j++)
                {
                    if(!fit(state[j],cur[i])) continue;
                    for(int k=1;k<=cnt;k++)
                    {
                        if(!fit(state[k],cur[i-1])) continue;
                        if(state[j]&state[k]) continue;
                        dp[i][j] = (dp[i][j]+dp[i-1][k])%MOD;
                    }
                }
            }
            int ans = 0;
            for(int i=1;i<=cnt;i++) ans = (ans+dp[N][i])%MOD;
            printf("%d
    ",ans);
        }    
    }
  • 相关阅读:
    break和continue
    while循环嵌套
    while循环语句
    SDUT 2766-小明传奇2(母函数)
    那些奇妙的&quot;大师&quot;是怎样炼成的(科学、迷信、心理)
    深入理解Linux字符设备驱动
    [从头学数学] 第162节 锐角三角函数
    iOS将数组中的内容分拼接成字符串
    win10 UWP 全屏
    杂(三)-The type java.lang.Object cannot be resolved It is indirectly referenced ...
  • 原文地址:https://www.cnblogs.com/helica/p/5037856.html
Copyright © 2020-2023  润新知