poj3254:Corn Fields(状压DP)

来源:互联网 发布:js按钮current trigger 编辑:程序博客网 时间:2024/05/20 10:15

传送门

题意:
有一片nm的土地(n12,m12),有些格子可以放牛,但要求放牛的格子不能相邻,求有多少种放牛方案。

题解:
首先O(n(2m)(2m))次方的DP很好想,但是要超时,考虑优化:
1.无用状态很多,先把所有有用状态预处理。判断有用状态:

status1&(status1<<1)==0

2.转移时把map压进int ,O(1)判断对于当前行状态是否合法。

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<vector>#include<map>#include<set>using namespace std;inline int read(){    char ch=getchar();int i=0,f=1;    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}    while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}    return i*f;}const int mod=1e8;int n,m,mp[15],now;int dp[2][(1<<12)+50];int status[(1<<12)+50],tot;inline bool valid(int sta){    return (sta&(sta<<1))==0;}int main(){    n=read(),m=read();    for(int i=1;i<=n;i++)        for(int j=0;j<m;j++)            mp[i]|=((read()^1)<<j);    int lim=(1<<m)-1;    for(int i=0;i<=lim;i++)        if(valid(i))status[++tot]=i;    dp[now][1]=1;    for(int i=1;i<=n;i++){        now^=1;        for(int j=1;j<=tot;j++){            dp[now][j]=0;            if(status[j]&mp[i])continue;            for(int k=1;k<=tot;k++){                if(status[j]&status[k])continue;                (dp[now][j]+=dp[now^1][k])%=mod;            }        }    }    int ans=0;    for(int i=1;i<=tot;i++)(ans+=dp[now][i])%=mod;    cout<<ans<<endl;    return 0;}
原创粉丝点击