[BZOJ1725][Usaco2006 Nov]Corn Fields牧场的安排(状压dp)

来源:互联网 发布:c语言贪吃蛇程序代码 编辑:程序博客网 时间:2024/06/05 07:06

题目描述

传送门

题解

预处理出状态每一行是否可行、两两关系是否可行。
状态:f[i][j]表示种到第i行,第i行状态为j的方案数。
转移:f[i][j]=(f[i][j]+f[i-1][k])%Mod;j和k分别表示这一行和上一行的状态。
初始化:f[1][所有状态]=1,其余为0
目标:i=0totf[n][i]其中tot为状态总数

代码

#include<iostream>#include<cstring>#include<cstdio>using namespace std;const int N=13;const int Mod=1e8;int n,m,tot,x,s[N],mi[N],state[N],f[N][1<<(N-1)],ans;bool line[1<<(N-1)],ok[1<<(N-1)][1<<(N-1)],situ[N][1<<(N-1)];int main(){    mi[0]=1; for (int i=1;i<N;++i) mi[i]=mi[i-1]<<1;    scanf("%d%d",&n,&m); tot=(1<<m)-1;    for (int i=1;i<=n;++i){        for (int j=m;j>=1;--j) scanf("%d",&s[j]); x=0;        for (int j=1;j<=m;++j) x+=mi[j-1]*s[j]; state[i]=x;    }    for (int i=0;i<=tot;++i)       if (((i>>1)&i)==0)        line[i]=true;    for (int i=0;i<=tot;++i) if (line[i])      for (int j=0;j<=tot;++j) if (line[j])        if ((i&j)==0)           ok[i][j]=true;    for (int i=1;i<=n;++i)      for (int j=0;j<=tot;++j)        if ((state[i]|j)==state[i])          situ[i][j]=true;    for (int i=0;i<=tot;++i) if (situ[1][i]&&line[i]) f[1][i]=1;    for (int i=2;i<=n;++i)      for (int j=0;j<=tot;++j)        if (line[j]&&situ[i][j])          for (int k=0;k<=tot;++k)            if (line[k]&&situ[i-1][k])              if (ok[j][k])                f[i][j]=(f[i][j]+f[i-1][k])%Mod;    for (int i=0;i<=tot;++i) ans=(ans+f[n][i])%Mod;    printf("%d\n",ans);}

总结

内存算好!
本来1A的题手残内存多打了嘿嘿嘿

0 0
原创粉丝点击