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\n");
else printf("Yes\n");
n=read();
}
return 0;
}
弱者就是会被欺负呀

浙公网安备 33010602011771号