状压DP

牧场的安排

 

:将每行输入的数字转换为十进制,然后预处理出所有满足题意的状态并存储于 sta ,再处理出单独一行时候的方案数并存储于 dp1,sta  枚举第 i 行的状态,判断第 j = i-1行的状态,并更新dpi , j ,最后累和即可

#include <bits/stdc++.h>
using namespace std;
#define ll long long
using namespace std;
const int mod = 1e8;/// 998244353;
const int mxn = 15 +7;
ll _,m,n,t,k,ans;
int dp[mxn][1<<13] , a[mxn][mxn] , f[mxn] , sta[1<<13] ;
void solve()
{
    while(cin>>m>>n){
        memset(f,0,sizeof(f));
        memset(sta,0,sizeof(sta));
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=m;i++){ /// 
            for(int j=1;j<=n;j++){
                cin>>a[i][j];
                f[i] = (f[i]<<1) + a[i][j];
            }
        }
        ll last = (1<<n);
        for(int i=0;i<last;i++){ /// 
            if(( (i&(i<<1))==0) && ((i&(i>>1))==0) )
                sta[i] = 1 ;
        }
        for(int i=0;i<last;i++){/// 状态合理 , 输入满足状态
            if(sta[i]==1 && ( (i&f[1]) ==i ) )
                dp[1][i] = 1 ;
        }
        for(int i=2;i<=m;i++){
            for(int j=0;j<last;j++){
                if(sta[j]==1 && ( (f[i] & j) == j) ){
                    for(int k=0;k<last;k++) /// i-1 行状态
                        if((j&k)==0)
                            dp[i][j] = (dp[i][j]+dp[i-1][k])%mod;
                }
            }
        }
        ans = 0 ;
        for(int i=0;i<last;i++)
            ans = (ans+dp[m][i])%mod;
        cout<<ans<<endl;
    }
}
int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    solve();
}
AC

 

posted @ 2020-07-28 12:33  __MEET  阅读(213)  评论(0编辑  收藏  举报