题目
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2795
题意
x * y的巧克力,问能不能恰好切成n份(只能整数切),每块大小恰好ai
思路
明显,记忆化搜索。
这里参照刘书使用了sum来通过长计算宽
感想:
这种需要枚举子状态的题总是不敢枚举
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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 = 101; const int MAXSTA = 1 << 16; 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] != -1)return ok[r][sta]; if (sum[sta] % r) return ok[r][sta] = 0; if ((sta & -sta) == sta)return ok[r][sta] = 1; int c = sum[sta] / r; assert(r >= c); for (int substa = (sta - 1) & sta; substa != 0; substa = (substa - 1) & sta) { if (sum[substa] * 2 < sum[sta])continue; if (sum[substa] % r == 0) { 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] = 1; } } else if(sum[substa] % c == 0){ 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] = 1; } } } return ok[r][sta] = 0; } 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 = 1;cin>>n && n; ti++) { memset(ok, -1, sizeof ok); int x, y; cin >> x >> y; for (int i = 0; i < n; i++) { cin >> a[i]; } maxsta = 1 << n; for (int sta = 0; sta < maxsta; sta++) { sum[sta] = 0; for (int i = 0; i < n; i++) { if (sta & (1 << i))sum[sta] += a[i]; } } if (sum[maxsta - 1] == x * y && check(max(x, y), maxsta - 1)) { printf("Case %d: Yes ", ti); } else { printf("Case %d: No ", ti); } } return 0; }