d390: 00562 - Dividing coins

Tags: subset-sum


出處:https://zerojudge.tw/ShowProblem?problemid=d390
提交:https://zerojudge.tw/Submissions?problemid=d390&account=allllllan123456


問題:給定 $m\in[0,100]$ 個數字 $\in[1,500]$,問你把這些數字「盡量平分 (總和)」為兩堆之後它們的差距 (最小) 是多少。


解法:此乃子集和問題,先算出總和 S 之後把這些數字用最佳策略塞進容量 S/2 的箱子內,那最後此箱子內的總體積就是其中一堆的和。數字多但總容量低,很適合用背包問題的 DP 算法。


 1#include <bits/stdc++.h>
 2using namespace std;
 3
 4int main() { ios_base::sync_with_stdio(false); cin.tie(0); // IO 優化
 5    int T; cin >> T;
 6    while (T--) {
 7        int v[100], dp[25001]={0}, sum=0, m; cin >> m;
 8        for (int i=0; i<m; i++)
 9            cin >> v[i], sum += v[i];
10        for (int i=0; i<m; i++)
11            for (int j=sum/2; j>=v[i]; j--)
12                dp[j] = max(dp[j], dp[j-v[i]] + v[i]);
13        cout << (sum-dp[sum/2]) - dp[sum/2] << '\n';
14    }
15    return 0;
16}

no image