【POJ3254】coinfield

状压dp初步。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 600
#define yql 1000000000
int n,m,top,a[N],v[N],dp[20][N],now[N];
inline bool lineck(int x){return  (x&(x<<1))?0:1;}
inline void init(){
    top=0;int sum=1<<n;
    for(int i=0;i<sum;i++)if(lineck(i))v[++top]=i;
}
inline bool fit(int x,int k){return (x&now[k])?0:1;}
inline int jcnt(int x){
    int cnt=0;
    while(x){++cnt;x&=(x-1);}
    return cnt;
}
inline int read(){
    int f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}
int main(){
    while(scanf("%d%d",&m,&n)!=EOF){
        init();memset(dp,0,sizeof(dp));
        for(int i=1;i<=m;i++){
            now[i]=0;int x;
            for(int j=1;j<=n;j++){x=read();if(!x)now[i]+=(1<<(n-j));}
        }
        for(int i=1;i<=top;i++)if(fit(v[i],1))dp[1][i]=1;
        for(int i=2;i<=m;i++)for(int k=1;k<=top;k++){
            if(!fit(v[k],i))continue;
            for(int j=1;j<=top;j++){
                if(!fit(v[j],i-1))continue;
                if(v[j]&v[k])continue;
                dp[i][k]=(dp[i][k]+dp[i-1][j])%yql;
            }
        }
        int ans=0;
        for(int i=1;i<=top;i++)ans=(ans+dp[m][i])%yql;
        printf("%d
",ans);
    }
}
原文地址:https://www.cnblogs.com/zcysky/p/6995065.html