点菜问题(北京大学复试上机题)(0-1背包问题)

点菜问题(北京大学复试上机题)(0-1背包问题)

题目描述:

北大网络实验室经常有活动需要叫外卖,但是每次叫外卖的报销经费的总额最大为C元,有N种菜可以点,经过长时间的点菜,网络实验室对于每种菜 i 都有一个量化的评价分数(表示这个菜可口程度),为Vi,每种菜的价格为Pi, 问如何选择各种菜,使得在报销额度范围内能使点到的菜的总评价分数最大。
注意:由于需要营养多样化,每种菜只能点一次。

输入格式:

输入的第一行有两个整数C和N,C代表总共能够报销的额度,N代表能点菜的数目。
接下来的N行每行包括两个整数Pi和Vi,分别表示第 i 道菜的价格和评价分数。

输出格式:

输出共一行,一个整数,表示在报销额度范围内,所点的菜能够得到的最大评价分数。

数据范围:

1≤C≤1000,
1≤N≤100,
1≤Pi,Vi≤100

输入样例: 输出样例:
90 4
20 25
30 20
40 50
10 18
95

题解(以本题内容作答,和0-1背包问题思路完全一致)

一、二维解法

解题思路:
  • 状态定义:dp(i,j)表示前 i 道菜品,在报销额度为 j 的情况下的最大总评价分数。
  • 分支情况(状态转移方程):对于前 i 道菜品的总评价分数dp(i,j)
    • 不选择第 i 道菜品,那么dp(i,j) = dp(i - 1, j),即和前i - 1道菜的总评价分数一致;
    • 选择第 i 道菜品,那么dp(i,j) = dp(i - 1, j - Pi) + Vi,即为前 i - 1道菜品在报销额度为j - Pi的最大总评价分数第 i 道菜品的评价分数之和
  • 那么什么时候加入第 i 道菜,什么时候不加入第 i 道菜呢?(第 i 道菜的价格记录在price[i - 1],评价分数记录在score[i - 1],报销额度是 j
    • 第一种情况是,当我们第 i 道菜的价格大于报销额度 j 时(即price[i - 1] > j),显而易见,不能加入。
    • 第二种情况是,第 i 道菜的价格小于报销额度(即price[i - 1] < j)时,若加入第 i 道菜后,前 i 道菜的总评价分数大于不加入第 i 道菜时前 i 道菜的总评价分数, 即dp[i - 1, j] < dp[i - 1, j - price[i - 1]] + score[i - 1]时,选择加入。
  • 综上所述,便有核心代码:
if (price[i - 1] > j)
	dp[i][j] = dp[i - 1][j];
else
	dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - price[i - 1]] + score[i - 1]);
AC代码:
#include <iostream>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值