HDU-2191 完全背包

点击链接打开此题目


题目大意:有n个经费和m种大米,每种大米都只有有限袋,且每种大米有特定的重量和价格。求最多用n个钱可以购买的大米重量最大为多少?


题目解析:开始的时候以为是要用贪心算法来求解的,但是一直WA,百思不得其解,无奈看了网上的讲解,才知道了问题所在。

       为什么不能用贪心算法呢?在求最优解的问题中,最优解问题大部分都可以拆分成一个个的子问题,我们常用的贪心算法和动态规划本质上是对子问题树的修剪。在用动态规划时,我们对每一个子树的根,求出下面每一个叶子的值,并且以其中的最优值作为自身的值,其它的值舍弃。而在用贪心算法时,要保证在全体最优解的情况下一定满足局部最优解,即每一个子树的根的值不取决于其下的子节点,而取决于自身。

       在这道题中,因为总钱数有限,当选定一种大米时,就相当于限制了其他种类大米的购买量,所以不能用贪心算法。

      也可以从另一种方式考虑,要实现贪心算法,就是要让每单位的钱购买到更多质量的大米。然而这道题中大米只能成袋购买,所以最终可能会有剩余的钱,这相当于减低了每单位钱的利用率,而降低的利用率是无法计算的(想要计算降低的利用率,肯定要知道最大利用率。而如果知道单位钱的最大利用率,这道题就不用做了偷笑),所以不能用贪心算法。

(以上啰嗦了那么多,只是为了说明不能用贪心算法大笑

       在这道题中,价钱一定,相当于确定了容积,接下来就是要求这些容积中的最大价值。又因为每种大米都有有限袋,典型的完全背包问题,可以转化为01背包问题,用动态规划来求解。

下面是AC了的代码:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;

//定义每种大米的结构体
struct node
{
	int p;//每袋的价格
	int h;//每袋的重量
	int c;//对应种类大米的袋数
}rice[101];

int dp[101];
int main()
{
	int C;//C组测试用例
	cin>>C;
	while(C--)
	{
		memset(dp,0,sizeof(dp));
		int m,n;//经费的金额、大米的种类
		cin>>n>>m;
		for(int i=1;i<=m;i++)
			cin>>rice[i].p>>rice[i].h>>rice[i].c;
		
        for(int i=1;i<=m;i++)//外层01背包
        {
            for(int j=1;j<=rice[i].c;j++)//内层01背包
            {
                for(int k=n;k>=rice[i].p;k--)
                {
                    dp[k]=max(dp[k],dp[k-rice[i].p]+rice[i].h);//动态规划
                }
            }
        }

		cout<<dp[n]<<endl;
	}
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值