[HAOI2008]硬币购物(动态规划、容斥、搜索)

传送

【题意】4种各有价值的硬币,t组数据,各给出一组硬币的数量,分别求满足给定价值的硬币方案数。

【解题】

读完题第一反应:摆花? 尝试写了个搜索,无果。苦思难解,看了题解发现要用完全背包预处理,还有神奇的容斥。emmmmm涨了一波见识

bj加减符号这个处理还是蛮有意思的  容斥风格; and 我还是想摆花嘤

#include <bits/stdc++.h>
#define sc(x) scanf("%lld", &x)
#define fr(i, n) for (register int i = 1; i <= n; i++)
#define int long long
const int N = 100050;
int t, d[5], c[5], f[N], ans, s;
void dfs(int x, int k,
         int bj) {  //定义和摆花差不多,不过k这里表示还需要的金额数(倒着dp),bj用来记录加还是减(容斥
    if (k < 0)
        return;
    if (x > 4) {
        ans += f[k] * bj;
        return;
    }
    //容斥容斥容斥
    dfs(x + 1, k, bj);
    dfs(x + 1, k - (d[x] + 1) * c[x], -bj);
}
signed main() {  
    fr(i, 4) { std::cin >> c[i]; }
    std::cin >> t;  
    f[0] = 1;
    fr(i, 4) for (int j = c[i]; j <= 100001; j++) f[j] += f[j - c[i]];
    while (t--) {
        ans = 0;
        fr(i, 4) { std::cin >> d[i]; }
        std::cin >> s; 
        dfs(1, s, 1);
        printf("%lld
", ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/phemiku/p/11820020.html