UVa Live 4794 - Sharing Chocolate 枚举子集substa = (s - 1) & substa,记忆化搜索 难度: 2

时间:2023-03-08 19:32:16

题目

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2795

题意

x * y的巧克力,问能不能恰好切成n份(只能整数切),每块大小恰好ai

思路

明显,记忆化搜索。

这里参照刘书使用了sum来通过长计算宽

感想:

这种需要枚举子状态的题总是不敢枚举

代码

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <tuple>
#define LOCAL_DEBUG
using namespace std;
typedef tuple<int, int, int> MyTask;
typedef pair<int, double> MyPair;
const int MAXN = ;
const int MAXSTA = << ;
int ok[MAXN][MAXSTA];
long long sum[MAXSTA];
int n;
int a[MAXN];
int maxsta; int check(int r, int sta) {
if (ok[r][sta] != -)return ok[r][sta];
if (sum[sta] % r) return ok[r][sta] = ;
if ((sta & -sta) == sta)return ok[r][sta] = ;
int c = sum[sta] / r;
assert(r >= c);
for (int substa = (sta - ) & sta; substa != ; substa = (substa - ) & sta) {
if (sum[substa] * < sum[sta])continue;
if (sum[substa] % r == ) {
int othersubsta = sta ^ substa;
int subr = r;
int subc = sum[substa] / r;
int othersubr = r;
int othersubc = c - subc;
if (check(max(subr, subc), substa) && check(max(othersubr, othersubc), othersubsta)) {
return ok[r][sta] = ;
}
}
else if(sum[substa] % c == ){
int othersubsta = sta ^ substa;
int subr = sum[substa] / c;
int subc = c;
int othersubr = r - subr;
int othersubc = c;
if (check(max(subr, subc), substa) && check(max(othersubr, othersubc), othersubsta)) {
return ok[r][sta] = ;
}
}
}
return ok[r][sta] = ;
} int main() {
#ifdef LOCAL_DEBUG
freopen("C:\\Users\\Iris\\source\\repos\\ACM\\ACM\\input.txt", "r", stdin);
//freopen("C:\\Users\\Iris\\source\\repos\\ACM\\ACM\\output.txt", "w", stdout);
#endif // LOCAL_DEBUG
int T;
//cin >> T;
for (int ti = ;cin>>n && n; ti++) {
memset(ok, -, sizeof ok);
int x, y;
cin >> x >> y;
for (int i = ; i < n; i++) {
cin >> a[i];
}
maxsta = << n;
for (int sta = ; sta < maxsta; sta++) {
sum[sta] = ;
for (int i = ; i < n; i++) {
if (sta & ( << i))sum[sta] += a[i];
}
}
if (sum[maxsta - ] == x * y && check(max(x, y), maxsta - )) {
printf("Case %d: Yes\n", ti);
}
else {
printf("Case %d: No\n", ti);
}
} return ;
}