UVa Live 4794

题目

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 = 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;
}
View Code
原文地址:https://www.cnblogs.com/xuesu/p/10468778.html