[BZOJ 1725][Usaco2006 Nov]Corn Fields牧场的安排:状压DP

来源:互联网 发布:5357端口 编辑:程序博客网 时间:2024/06/05 10:56

点击这里查看原题

用二进制串表示每一行的摆放情况,预处理出各个状态间的转移关系即可。
f[i][j]表示第i行按状态j摆放的方案数。

/*User:SmallLanguage:C++Problem No.:1725*/#include<bits/stdc++.h>#define ll long long#define inf 999999999using namespace std;const int M=(1<<12)+5,mod=1e8;int f[13][M],n,m,c[M],tot,num[M],d[13],ans;bool vis[M][M];void pre(){    for(int i=0;i<(1<<m);i++){        if(i&(i>>1)) continue;        c[++tot]=i;        for(int j=i;j;j>>=1) num[tot]+=(j&1);    }    for(int i=1;i<=tot;i++)        for(int j=1;j<=tot;j++)            vis[i][j]=(c[i]&c[j])==0;}int main(){    freopen("data.in","r",stdin);//    scanf("%d%d",&n,&m);    pre();    for(int i=1;i<=n;i++){        int x;        for(int j=0;j<m;j++){            scanf("%d",&x);            d[i]|=x<<j;        }    }    for(int i=1;i<=tot;i++) if((c[i]&d[1])==c[i]) f[1][i]=1;    for(int i=2;i<=n;i++){        for(int j=1;j<=tot;j++){            if((c[j]&d[i])!=c[j]) continue;            for(int k=1;k<=tot;k++){                if(vis[j][k]) f[i][j]=(f[i][j]+f[i-1][k])%mod;            }        }    }    for(int j=1;j<=tot;j++) ans=(ans+f[n][j])%mod;    printf("%d\n",ans);    return 0;}
0 0
原创粉丝点击