Problem Description
電子科大本部食堂的飯卡有一種很詭異的設計,即在購買之前判斷餘額。如果購買一個商品之前,卡上的剩餘金額大於或等於5元,就一定可以購買成功(即使購買後卡上餘額爲負),否則無法購買(即使金額足夠)。所以大家都希望儘量使卡上的餘額最少。
某天,食堂中有n種菜出售,每種菜可購買一次。已知每種菜的價格以及卡上的餘額,問最少可使卡上的餘額爲多少。
Input
多組數據。對於每組數據:
第一行爲正整數n,表示菜的數量。n<=1000。
第二行包括n個正整數,表示每種菜的價格。價格不超過50。
第三行包括一個正整數m,表示卡上的餘額。m<=1000。
n=0表示數據結束。
Output
對於每組輸入,輸出一行,包含一個整數,表示卡上可能的最小余額。
Sample Input
1
50
5
10
1 2 3 2 1 1 2 3 2 1
50
0
Sample Output
-45
32
分析:
如果開始的 m 小於 5 那麼不可以買任何的東西直接輸出 m 即可。
否則,先拿出 5 元買最貴的菜,
【不用管 5 元是否有剩餘, 因爲 5 元是可以買東西的基礎,那麼這裏減去了 5 剩下的錢就可以隨便亂買了】
剩下的套用 01 揹包即可。
m-5 看成揹包容量。
每種菜的價格看成是花費的代價和得到的價值
然後輸出剩餘的錢:開始買最貴的剩下的錢+套用揹包思想剩下的錢 【均可以爲負數】
AC代碼:
#include <iostream>
#include <vector>
#include <utility>
#include <cstring>
#include <algorithm>
#include <map>
#include <queue>
#include <stack>
#include <cstdio>
#include <set>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long ll;
#define INF 0X3F3F3F
#define MAXN 1005
int w[MAXN];
int dp[MAXN];
int main() {
ios;
int n, m;
while (cin >> n, n) {
memset(dp, 0, sizeof(dp));
memset(w, 0, sizeof(w));
for (int i = 1; i <= n; i++) {
cin >> w[i];
}
cin >> m;
sort(w + 1, w + 1 + n);
if (m < 5) {
cout << m << endl;
continue;
}
for (int i = 1; i < n; i++) {
for (int j = m - 5; j >= w[i]; j--)
dp[j] = max(dp[j], dp[j - w[i]] + w[i]);
}
cout << m - dp[m-5] - w[n] << endl;
}
return 0;
}