[VJ][简单背包]杭电饭卡
饭卡
Description
电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额。如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够)。所以大家都希望尽量使卡上的余额最少。
某天,食堂中有n种菜出售,每种菜可购买一次。已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少。
Input
多组数据。对于每组数据:
第一行为正整数n,表示菜的数量。n<=1000。
第二行包括n个正整数,表示每种菜的价格。价格不超过50。
第三行包括一个正整数m,表示卡上的余额。m<=1000。
n=0表示数据结束。
Output
对于每组输入,输出一行,包含一个整数,表示卡上可能的最小余额。
Examples
Input
1 50 5 10 1 2 3 2 1 1 2 3 2 1 50 0
Output
-45 32
正确解法:
自己瞎造出来的算法错了qaq,应该先把 5这个数减下去,就可以转化为 有m个钱,买东西最多能买多少金额的?
因为前期减去了5嘛,所以要特殊一下,如果m直接就<0,就直接输出m,当m>=5时,才有了下面的东西。
由背包问题很容易得出 f[m]=max( f[m], f[m-a[i]]+a[i]); 0<i<n ;
然后就是总共的钱减去算出的 f[m] ,再减去a[i]中最大的那个数!
因为前面所算的所有都是在m-5的基础上,m-5是永远大于0的,减去最大的那个,使金额小于0。才是最后得出的答案啊!
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<string> 5 #include<cstring> 6 #include<algorithm> 7 using namespace std; 8 int n,m; 9 int f[1010], a[1010] = {0}; 10 int main() 11 { 12 while (cin >> n) 13 { 14 if (n == 0) break; 15 memset(a, 0, sizeof(a)); 16 memset(f, 0, sizeof(f)); 17 for (int i = 0; i < n; i++) 18 cin >> a[i]; 19 cin >> m; 20 m = m - 5; 21 if (m >= 0) 22 { 23 sort(a, a + n); 24 for (int i = 0; i < n - 1; i++) 25 for (int j = m; j >= a[i]; j--) 26 f[j] = max(f[j], f[j - a[i]] + a[i]); 27 cout << m + 5 - f[m] - a[n - 1] << endl; 28 } 29 else 30 cout << m + 5 << endl; 31 } 32 return 0; 33 }
No matter how you feel, get up , dress up , show up ,and never give up.