zoukankan      html  css  js  c++  java
  • HDU 2844 Coins 多重背包

    HDU 2844 Coins 多重背包

    题意

    给你n种硬币,每个硬币的金额为(Ai),数量为(Ci),然后给你一个范围(m),问在使用这些硬币可以组成多少种金额,要求组成的金额在((1, m))范围内。

    解题思路

    使用多重背包来进行解决这个问题。这样我们能够获得每种金额(可以看作背包的容量)下使用硬币组成的最多的金额数量。二重背包结束后,然后使用for循环,遍历这里dp里面(dp[i]==i)的个数,这个个数就是答案。

    代码实现

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=107; //硬币的种类数量
    const int maxm=1e5+7; //金额的最大范围
    int a[maxn], c[maxn];
    int n, m;
    int dp[maxm];
    int main()
    {
    	while(scanf("%d%d", &n, &m) && (n+m)!=0)
    	{
    		for(int i=1; i<=n; i++)
    			scanf("%d", &a[i]);
    		for(int i=1; i<=n; i++)
    			scanf("%d", &c[i]);
    		memset(dp, 0, sizeof(dp));
            //下面就是二重背包的主要代码,可以说就是模板了
    		for(int i=1; i<=n; i++) //遍历前i种硬币
    		{
    			int min_num=min(c[i], m/a[i]); //选择这种硬币的最少数量
    			for(int k=1; min_num>0; k<<=1) //使用二进制优化
    			{
    				if(k>min_num) //如果最后不够k个了,就直接赋值给k
    					k=min_num;
    				min_num-=k;
    				for(int j=m; j>=a[i]*k; j--)
    				{
    					dp[j]=max(dp[j], dp[j-a[i]*k]+a[i]*k);
    				}
    			}	
    		}
    		int ans=0;
    		for(int i=1; i<=m; i++)//这里遍历一遍dp里面dp[i]==i的个数
    			if(dp[i]==i)
    				ans++;
    		printf("%d
    ", ans); //输出个数就是答案
    	}
    	return 0;
    }
    
    欢迎评论交流!
  • 相关阅读:
    PAT甲级1137Final Grading
    晚测6
    模拟15
    模拟14
    模拟13
    晚测5
    晚测4
    模拟11
    7012. 2021.03.15【2021省赛模拟】十
    7011. 2021.03.13【2021省赛模拟】nonintersect
  • 原文地址:https://www.cnblogs.com/alking1001/p/11875939.html
Copyright © 2011-2022 走看看