LA 4794 Sharing Chocolate

 题意:给出一个长宽确定的矩形,每次可以沿一条直线把它分割成两块长宽都为整数的矩形,问能否通过多次操作得到n块面积分别为a1,a2...an的矩形。


分析:白书原题,状压DP+记忆化搜索。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n,x,y,num,a[16],sum[1<<15],jud[101][1<<15],val[101][1<<15];
int count(int x)
{
	int sum = 0;
	while(x)
	{
		sum++;
		x = x & (x-1);
	}
	return sum;
}
bool Find(int c,int s)
{
	if(jud[c][s]) return val[c][s];
	if(count(s) == 1) return true;
	bool flag = false;
	int w = sum[s] / c; 
	for(int i = (s-1) & s;i;i = (i-1) & s)
	 if(2*sum[i] >= sum[s])
	 {
 		 if(sum[i] % c == 0)
		 {
			 flag = Find(c,i) && Find(c,s-i);
		 } 
		 if(flag) break;
		 if(sum[i] % w == 0)
		 {
			 int x = sum[i] / w;
			 flag = Find(max(x,w),i) && Find(max(c-x,w),s-i);
		 }
		 if(flag) break;
	 }
	jud[c][s] = true;
	val[c][s] = flag;
	return flag;
} 
int main()
{
	cin.sync_with_stdio(false);
	while(cin >> n && n)
	{
		cout<<"Case "<<++num<<":"<<" ";
		memset(sum,0,sizeof(sum));
		memset(jud,0,sizeof(jud));
		cin>>x>>y;
		for(int i = 1;i <= n;i++) cin>>a[i];
		int tot = (1<<n)-1;
		for(int i = 1;i <= tot;i++)
		 for(int j = 1;j <= n;j++)
		  if((i & (1<<(j-1))) == (1<<(j-1))) sum[i] += a[j];
		if(sum[tot] != x*y)
		{
			cout<<"No"<<endl;
			continue;	
		} 
		if(Find(max(x,y),tot)) cout<<"Yes"<<endl;
		else cout<<"No"<<endl; 
	}
 } 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值