UVA 562——Dividing coins【01揹包平衡】

題目傳送門
在這裏插入圖片描述

題意:

給你一堆硬幣,讓你分成兩堆,分別給A,B兩個人,求兩人得到的最小差。

分析:

首先算出每個硬幣的權值之和sum。然後以sum / 2爲揹包容量,求出能裝出的最大包。答案就是sum - 最大包 * 2

原理:

如果剛好可以將硬幣分爲sum / 2和sum / 2那就最好了,答案直接是0。但如果分不到,那麼其中一組的權值和肯定是sum / 2的前驅(也就是能湊出的最大的權值和且<=sum / 2)。所以,揹包算出這個前驅即可。那麼最小差就是另一組權值和 - 前驅 = sum - 前驅 * 2

AC代碼:

#include <iostream>
#include <vector>
#include <utility>
#include <cstring>
#include <algorithm>
#include <map>
#include <queue>
#include <stack>
#include <cstdio>
#include <fstream>
#include <set>
using namespace std;
typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

#define MAXN 50005
int w[MAXN];
int dp[MAXN];
int main() {
	ios;
	int T;
	while (cin >> T) {
		while (T--) {
			memset(dp, 0, sizeof(dp));
			int n;
			cin >> n;
			int avg = 0;
			int sum = 0;
			for (int i = 1; i <= n; i++) {
				cin >> w[i];
				sum += w[i];
			}
			avg = sum / 2;
			for (int i = 1; i <= n; i++) {
				for (int j = avg; j >= w[i]; j--)
					dp[j] = max(dp[j], dp[j - w[i]] + w[i]);
			}
			cout << sum - 2 * dp[avg] << endl;
		}
	}

	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章