C++ 动态规划-背包类例题

来源:互联网 发布:linux screen 切换 编辑:程序博客网 时间:2024/05/18 10:30


(一)01背包变形


例1:分西瓜

已知有一堆西瓜,请帮忙将这一堆西瓜分成两堆,已知每个西瓜的重量,现在要求分成两堆的西瓜的重量的差最小

输入描述

第一行输入西瓜数量N (1 ≤ N ≤ 20)
第二行有N个数,W1, …, Wn (1 ≤ Wi ≤ 10000)分别代表每个西瓜的重量

输出描述

输出分成两堆后的质量差

样例输入

55 8 13 27 14

样例输出

3



此题好想的方法是:可以转化为01背包问题:假设总重是V,求背包容量为V/2的最大价值,这里价值就是重量

 【解法1】

#include <iostream>using namespace std;int n, V, hfV;int v[50001], c[50001];int f[50001];int main() {cin >> n;for(int i=1; i<=n; i++) cin >> v[i];for(int i=1; i<=n; i++) {V += v[i];c[i] = v[i];}hfV = V/2;for(int i=1; i<=n; i++) for(int j=hfV; j>=v[i]; j--)f[j] = max(f[j], f[j-v[i]] + c[i]);if(V % 2 == 0) cout << (hfV - f[hfV]) * 2 << endl;else cout << V - 2 * f[hfV] << endl;return 0;}

【解法2】bool f[j]表示能不能装满为重j的物品
#include <iostream>using namespace std;int n, V, hfV;int v[50001];bool f[50001];int main() {cin >> n;for(int i=1; i<=n; i++) cin >> v[i];for(int i=1; i<=n; i++) V += v[i];hfV = V/2;f[0] = 1;for(int i=1; i<=n; i++)for(int j=hfV; j>=v[i]; j--)f[j] = f[j] || f[j-v[i]];int maxv = 0; for(int i=hfV; i>=1; i--)if(f[i]) {maxv = i;break;}if(V % 2 == 0) cout << (hfV - maxv) * 2 << endl;else cout << V - 2 * maxv << endl;return 0;}


这一题是01背包的经典变形:满箱背包