• LA4794 Sharing Chocolate


     

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

    与分蛋糕的生日快乐有点像。记忆化搜索、枚举子集。

    由于n很小可以直接状压,s表示需要得到的巧克力的状态集合。

    因为每次所有的要得到的巧克力面积和等于r*c,可以根据这个剪枝,同时把状态f[r][c][s]变成二维f[r][s]。

    然后发现如果写return 1,2;最后会返回2。

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int maxn=17,maxs=(1<<15)+10;
    int n,r,c,tot[maxs];
    int f[110][maxs];
    
    int aa;char cc;
    int read() {
    	aa=0;cc=getchar();
    	while(cc<'0'||cc>'9') cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	return aa;
    }
    
    bool ok(int r,int s) {
    	if(f[r][s]) return f[r][s]-1;
    	if(s==(s&(-s))) return f[r][s]=2,1;
    	int x,y,c=tot[s]/r;
    	for(x=(s-1)&s;x;x=(x-1)&s) {
    		y=s-x;
    		if(tot[x]%c==0&&ok(r*tot[x]/tot[s],x)&&ok(r*tot[y]/tot[s],y)) return f[r][s]=2,1;
    		if(tot[x]%r==0&&ok(r,x)&&ok(r,y)) return f[r][s]=2,1;
    	}
    	return f[r][s]=1,0;
    }
    
    int main() {
    	n=read();int tt=0;
    	while(n) {
    		r=read();c=read(); int x;
    		memset(tot,0,sizeof(tot));
    		memset(f,0,sizeof(f));
    		for(int i=1;i<=n;++i) tot[1<<(i-1)]=read();
    		for(int i=1;i<(1<<n);++i) {
    			x=(i&(-i)); if(i==x) continue;
    			tot[i]=tot[x]+tot[i^x];
    		}
    		printf("Case %d: ",++tt);
    		if(r*c!=tot[(1<<n)-1]||!ok(r,(1<<n)-1)) printf("No
    ");
    		else printf("Yes
    ");
    		n=read();
    	}
    	return 0;
    }
    

      

    弱者就是会被欺负呀
  • 相关阅读:
    关于String重写的hashcode的代码分析
    自定义HashSet判重标准
    idea-Java文件结构
    java 带静态域的导出类创建时都发生了什么?
    seo初学
    关于事件冒泡和事件委托
    关于本地$.get(url,function(data)),异步获取数据
    FileReader上传图片
    关于随机生成颜色
    C语言贪吃蛇
  • 原文地址:https://www.cnblogs.com/Serene-shixinyi/p/7604093.html
Copyright © 2020-2023  润新知