POJ 3254 (状态压缩DP)

思路:状态压缩dp,用二进制位的1表示放了,0表示没有放。设dp[i][j],表示第i行状态为j时,前i行的方案数,状态转移方程就是 dp[i][j] += dp[i-1][k],j与k这两个状态不冲突。最后答案就是dp[n][1...top] 之和。


#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 15;
const int MOD = 100000000;
int dp[MAXN][400];
int top, tmp, n, m;
int map[MAXN], status[400];
void init(){
    top = 1;
    int up = 1 << m;
    memset(dp, 0, sizeof(dp));
    memset(map, 0, sizeof(map));
    for(int i = 0;i < up;i ++){
        if(i & (i << 1)) continue;
        status[top++] = i;
    }
}
int main(){
    //freopen("in.c", "r", stdin);
    while(~scanf("%d%d", &n, &m)){
        init();
        for(int i = 1;i <= n;i ++){
            for(int j = 0;j < m;j ++){
                scanf("%d", &tmp);
                if(!tmp) map[i] |= (1 << j);
            }
        }
        for(int i = 1;i < top;i ++){
            if(map[1] & status[i]) continue;
            dp[1][i] = 1;
        }
        for(int i = 2;i <= n;i ++){
            for(int j = 1;j < top;j ++){
                if(map[i] & status[j]) continue;
                for(int k = 1;k < top;k ++){
                    if(status[j] & status[k] || map[i-1] & status[k]) continue;
                    dp[i][j] += dp[i-1][k];
                    dp[i][j] %= MOD;
                }
            }
        }
        int ans = 0;
        for(int i = 1;i < top;i ++){
            ans += dp[n][i];
            ans %= MOD;
        }
        printf("%d\n", ans);
    }
    return 0;
}


posted on 2014-05-05 13:35  ~Love()  阅读(108)  评论(0编辑  收藏  举报

导航