• [BZOJ 1042] [HAOI2008] 硬币购物 【DP + 容斥】


    题目链接:BZOJ - 1042

    题目分析

    首先 Orz Hzwer ,代码题解都是看的他的 blog。

    这道题首先使用DP预处理,先求出,在不考虑每种硬币个数的限制的情况下,每个钱数有多少种拼凑方案。

    为了避免重复的方案被转移,所以我们以硬币种类为第一层循环,这样阶段性的增加硬币。

    一定要注意这个第一层循环要是硬币种类,并且初始 f[0] = 1。

    f[0] = 1;
    for (int i = 1; i <= 4; ++i) {
    	for (int j = B[i]; j <= MaxS; ++j) {
    		f[j] += f[j - B[i]];
    	}
    }
    

    之后对于每个询问 (A1, A2, A3, A4, S) ,根据容斥原理,我们要求的答案 Ans 就是 f[S] - (硬币1超限制的方案数) - (硬币2超限制的方案数) - (硬币3超限制的方案数) - (硬币4超限制的方案数) + (硬币1,2超限制的方案数) + (硬币1,3超限制的方案数) + (硬币1,4超限制的方案数) + .... - (硬币1,2,3超限制的方案数) - ... + (硬币1,2,3,4超限制的方案数) 。  

    怎样求硬币1超限制的方案数呢?我们只要先固定取 (A1+1) 个硬币1,剩余的钱数随便取就可以了,就是 f[S - (A1+1) * V[1]] 。

    其余的情况都类似。

    容斥的部分使用搜索实现。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <cstring>
    
    using namespace std;
    
    const int MaxN = 7, MaxS = 100000;
    
    int n, S;
    int A[MaxN], B[MaxN];
    
    typedef long long LL;
    
    LL Ans;
    LL f[MaxS + 5];
    
    void DFS(int x, int k, int Sum) {
    	if (Sum < 0) return;
    	if (x == 5) {
    		if (k & 1) Ans -= f[Sum];
    		else Ans += f[Sum];
    		return;
    	}
    	DFS(x + 1, k + 1, Sum - (A[x] + 1) * B[x]);
    	DFS(x + 1, k, Sum);
    }
    
    int main() 
    {
    	for (int i = 1; i <= 4; ++i) scanf("%d", &B[i]);
    	scanf("%d", &n);
    	f[0] = 1;
    	for (int i = 1; i <= 4; ++i) {
    		for (int j = B[i]; j <= MaxS; ++j) {
    			f[j] += f[j - B[i]];
    		}
    	}
    	for (int i = 1; i <= n; ++i) {
    		for (int j = 1; j <= 4; ++j) scanf("%d", &A[j]);
    		scanf("%d", &S);
    		Ans = 0ll;
    		DFS(1, 0, S);
    		printf("%lld
    ", Ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    leetcode38.外观数列(循环匹配)
    leetcode35.搜索插入位置(遍历并进行大小判断)
    leetcode28.实现strStr()(暴力拆解,双指针,KMP算法)
    JavaScript对象
    数组迭代
    数组的用法:
    数组
    while与do while 区别 for循环的简介及break和continue的区别
    for循环语句
    if.......else语句子
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4183261.html
Copyright © 2020-2023  润新知