Codeforces Beta Round #85 (Div. 1 Only) C. Petya and Spiders

状压DP

可以发现,选择一个格子能够覆盖周围4个格子和它自己,问题转化成在n*m的网格中,选出尽量少的格子把其他格子全部覆盖。又因为n*m<=40,有min(n,m)<=6,不妨设n<m

dp[i][st1][st2]表示考虑前i列,第i列被覆盖的状态为st1,第i+1列为st2,其中st是一个二进制数,表示一个集合,的第i位为1表示这一竖行的第i个格子已经被覆盖了,反之没有被覆盖。

那么dp[i-1][st1][st2]能转移dp[i][i_st1][i_st2]的条件是st2|i_st1=(1<<n)-1因为如果这时候第i-1列还不能被完全覆盖,以后就再也不能了。转移的时候枚举当前列选择出那些格子,并预处理CUR[st],表示当前列选出的格子集合为st时,当前列被覆盖的格子集合。而下一列被覆盖的集合就是st,不用预处理。

#include <bits/stdc++.h>
#define maxn 20
#define maxm 100009
#define MOD 1000000007
using namespace std;
int n,m;
int dp[50][1<<6][1<<6];
int CUR[1<<6],bitcount[1<<6];
int main()
{
	scanf("%d%d",&n,&m);
	if(n>m)
		swap(n,m);
	for(int st=0;st<1<<n;st++)
	{
		for(int j=0;j<n;j++)
		{
			if((1<<j)&st)
			{
				CUR[st]|=(1<<j);
				if(j>0)
					CUR[st]|=(1<<(j-1));
				if(j<n-1)
					CUR[st]|=(1<<(j+1));
				bitcount[st]++;
			}
		}
	}
	for(int st=0;st<1<<n;st++)
	{
		dp[1][CUR[st]][st]=n-bitcount[st];
	}
	for(int i=2;i<=m;i++)
	{
		for(int st=0;st<1<<n;st++)
		{
			for(int last=0;last<1<<n;last++)
			{
				if((st|last)!=((1<<n)-1))
					continue;
				for(int cur=0;cur<1<<n;cur++)
				{
					dp[i][cur|CUR[st]][st]=max(dp[i][cur|CUR[st]][st],dp[i-1][last][cur]+n-bitcount[st]);
				}
			}
		}
	}
	int ans=0;
	for(int i=0;i<1<<n;i++)
		ans=max(ans,dp[m][(1<<n)-1][i]);
	printf("%d\n",ans);
	//system("pause");
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值