poj 3254(状态压缩dp)

// 题意:有一个n*m的矩阵 0代表不能种 1代表能种 求共有多少种种植方式
// dfs肯定超时 用状态压缩dp
// 最开始觉得状压dp也不是很省时 看别人博客优化
// 利用st数组来优化 st[i]表示第i行可以达到的最大状态 比如这一行为111 那么对应的二进制数就是 1+2+4 = 7
// 学习了别人的思路 dp[i][j] 表示第i行,状态为j的种植方式有多少种
// dp[i][j] = sum(dp[i - 1][k]) 条件:状态k和状态j不能冲突 即 k & j != 0
#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
#define mod 100000000
int st[15];
int dp[13][1<<12];
int isok(int a, int b)
{
    if((a & b) != b) return 0;
    if(b & (b >> 1)) return 0;
    return 1;
}
int main()
{
    int n, m, tmp;
    while(cin>>n>>m)
    {
        memset(dp, 0, sizeof dp);
        memset(st, 0, sizeof st);
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)
            {
                cin>>tmp;
                if(tmp)
                    st[i] += (1<<(j - 1));
            }
        
        dp[0][0] = 1;
        for(int i = 1; i <= n; i++)
        {
            for(int j = 0; j <= st[i]; j++)
            {
                if(!isok(st[i], j)) continue;
                for(int k = 0; k <= st[i - 1]; k++)
                {
                    if(k & j) continue;
                    dp[i][j] += dp[i - 1][k];
                    if(dp[i][j] >= mod) dp[i][j] -= mod;
                }
            }
        }
        long long ans = 0;
        for(int i = 0; i <= st[n]; i++)
        {
            ans += dp[n][i];
            if(ans >= mod) ans -= mod;
        }
        cout<<ans<<endl;
    }
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章