POJ3254-Corn Fields-状态压缩

//首先这道题目真的是好题,但是POJ太坑了,给的n和m的范围偏小了,一直WA,很无奈。

题目大意:给你一张n*m的草坪,每一块如果是1就表示可以放东西,0就不可以,你不可以在相邻的草上面放东西,问你最多能放几个;

题目解析:开始dp肯定从这一行上面的草坪开始转移,肯定要状态压缩,否则肯定超时并且不能记忆化搜索,有个小技巧,如果一个排列有两个相邻的肯定不可以,所以我们先判断x&(1<<x),如果不为0就表示有两个是相邻的,应该排除,把可以的存在sta[i]中,dp的时候枚举一下序列如果和上面的序列符合题意的话只要(x&y)==0;

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#define mod 1000000000;
using namespace std;
int main()
{
	int n,m,i,j,k,l,number,grass[20],dp[20][5010],temp,sta[5010],sum;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		memset(grass,0,sizeof(grass));
		memset(dp,0,sizeof(dp));
		memset(sta,0,sizeof(sta));
		number=0;
		for(i=0;i<n;i++)
		{
			for(j=0;j<m;j++)
			{
				scanf("%d",&temp);
				if(temp==1)
					grass[i]|=1<<j; 
			}
		}
		k=0;
		for(i=0;i<(1<<m);i++)
		{
			if((i&(i<<1))==0)
				sta[++k]=i;
		}
		for(i=1;i<=k;i++)
		{
			if((grass[0]|sta[i])==grass[0])
				dp[0][sta[i]]=1;
		}
		for(i=1;i<n;i++)
		{
			for(j=1;j<=k;j++)
			{
				if((sta[j]|grass[i])!=grass[i])
					continue;
				for(l=1;l<=k;l++)
				{
					if((sta[l]|grass[i-1])!=grass[i-1])
						continue;
					if((sta[l]&sta[j])==0)
						dp[i][sta[j]]=dp[i][sta[j]]+dp[i-1][sta[l]]%mod;
				}
			}
		}
		sum=0;
		for(i=1;i<=k;i++)
		{
			sum+=dp[n-1][sta[i]];
			sum%=mod;
		}
		printf("%d\n",sum);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值