原题
题意
电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额。
如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够)。
所以大家都希望尽量使卡上的余额最少。
某天,食堂中有n种菜出售,每种菜可购买一次。
已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少。
思路
01背包。
与单纯的01背包不同的是,题目中有“5元”的限制条件。
我们可以把饭卡的余额分为两部分,一部分为5元,一部分为剩下的钱。
则可以用5元购买最贵的菜,剩下部分的购买就是一个01背包问题。
你可能会想,如果这5元剩下了一些钱,另一部分也剩下了一些钱,那这些钱可不可能合起来再买更多的菜呢?
我们可以推导一下。
设最贵的菜为x
元,另一部分购买之后剩下的最少的钱为y
元,
则总共剩余的钱为5-x+y
。
如果你还想花这部分钱,则必须满足5-x+y>=5
,可以推出y>=x
,即只要满足这个条件就可以继续买。
既然y>=x
,则第二部分剩下的钱y一定大于等于所有的菜的价格,所以y
可以再买任何一种菜。
而01背包部分得到的解一定是最优解,所以y
一定是不能继续买了而剩下的钱,
也就是所有的菜都买过了,所以不能再买更多的菜。
值得注意的点
1.最贵的菜已经在“5元”的部分买过了,在01背包中需要跳过。
2.当饭卡中的钱不够5元时,需要额外处理。
代码
#include <iostream>
#include <algorithm>
using namespace std;