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;
}



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