HDU 2546——飯卡【01揹包 + 貪心】

題目傳送門

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章