- 题目考点:dp -- 01背包 (无脑dfs肯定T ,后面附上60分dfs吧)
- 题目大意:将a数组中的数分成两组,使得两组中的数的和尽量接近,输出两组数的和(若无法平均,优先输出较小的数)
- 题目分析:01背包问题,若a数组中的数总和为sum ,可以假想一个体积为sum / 2的背包,将其尽量装满即可
代码如下:
#include<iostream> #include<algorithm> using namespace std; const int N = 10010; // 100个苹果每个质量都是100的话,需要一个10000的背包 //所以dp数组至少需要5000, 这里奢侈了一把 int a[N], n, sum = 0; int dp[N]; int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d", &a[i]), sum += a[i]; int v = sum / 2; for(int i = 1; i <= n; i++) for(int j = v; j >= a[i]; j --) dp[j] = max(dp[j], dp[j - a[i]] + a[i]); printf("%d %d", dp[v], sum - dp[v]); return 0; }
60分dfs给大家助助兴:
#include<iostream> #include<algorithm> using namespace std; const int N = 110, INF = 0x3f3f3f3f; int a[N], sum = 0, n; int ans = 0; bool v[N]; void dfs(int w, int k) { if(k > n){ans = max(ans, w); return ;} if(w + a[k] <= sum / 2) dfs(w + a[k], k + 1); dfs(w, k + 1); } int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d", &a[i]), sum += a[i]; dfs(0, 1); printf("%d %d", ans, sum - ans); return 0; }