您的位置:首页 > 其它

POJ-3254 Corn Fields 状态压缩DP+滚动数组

2013-03-01 13:23 507 查看
  题目链接:http://poj.org/problem?id=3254

  状态压缩,用01分别表示pasture不能plant和能plant。转移方程:f[k][i]=sum{f[k-1][j] | j是能满足i的状体,不产生冲突},显然可以用滚动数组优化。

  详细的转移方法(上一个的状态设为k,i为所在行数):

    1,如果前一个pasture已被plant,那么下一个pasture必定不能plant,所以f[i][k&~(1<<j)]+=f[i-1][k];

    2,如果前一个pasture没有plant:

      a,下一个pasture不plant,那么f[i][k]+=f[i-1][k];

      b,如果下一个pasture的左边那个没有plant,即(k&(1<<(j-1)==0,那么这个pasture可以plant,则 f[p][k|(1<<j)]+=+f[!p][k]);

//STATUS:C++_AC_0MS_192KB
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define LL __int64
#define pdi pair<int,int>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int N=12,INF=0x3f3f3f3f,MOD=100000000;
const double DNF=100000000000;

int map

,f[2][(1<<N)+10];
int n,m;

int main()
{
//   freopen("in.txt","r",stdin);
int i,j,k,p,ans;
while(~scanf("%d%d",&n,&m))
{
ans=0;
mem(f,0);f[0][0]=p=1;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
scanf("%d",&map[i][j]);
for(i=0;i<n;i++){
for(j=0;j<m;j++,mem(f[p=!p],0)){
for(k=0;k<(1<<m);k++){
if(k&(1<<j))
f[p][k&~(1<<j)]=(f[p][k&~(1<<j)]+f[!p][k])%MOD;
else {
f[p][k]=(f[p][k]+f[!p][k])%MOD;
if((j && !(k&(1<<(j-1))) || !j ) && map[i][j])
f[p][k|(1<<j)]=(f[p][k|(1<<j)]+f[!p][k])%MOD;
}
}
}
}
p=!p;
for(i=0;i<(1<<m);i++)
ans=(ans+f[p][i])%MOD;

printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: