洛谷 P 2663 (二维费用背包)
题目描述
班级要组织一场综合能力竞赛,全班同学(N(100以内)个,N是偶数)分成两队互相竞争。老师找到了越越并给了越越一张全班同学综合能力测试的成绩,要求他从全班同学中选出一半(他自己也可能被选),并要求这些同学综合能力测试的成绩之和在不超过班级总分一半的前提下尽量达到最高。这样分成的两队实力是最平均的。越越堆着满脸的笑容找到了你,你就帮他写一个程序吧。
输入格式
第一行:学生个数N;第二行开始的N行每行一个同学的综合能力测试的成绩。
输出格式
输出一个数:N/2个同学的综合能力测试的成绩之和在不超过班级总分一半的前提下尽量达到的最高值。
输入输出样例
输入 #1
8 77 77 56 77 84 77 56 46
输出 #1
273
说明/提示
样例解释:总分550;总分的一半275;选择4名同学56 77 84 56 77 达到总分273;273是不超过275的最大值。(另一队的和是277)两队实力最接近。
二维费用背包:多开一维表示另一维费用,在一维费用背包的基础上 二重for是时候同时考虑两个费用即可
(丑陋的)Code:
#include<bits/stdc++.h> #define debug(x) cout << "[" << #x <<": " << (x) <<"]"<< endl #define pii pair<int,int> #define clr(a,b) memset((a),b,sizeof(a)) #define rep(i,a,b) for(int i = a;i < b;i ++) #define pb push_back #define MP make_pair #define LL long long #define ull unsigned LL #define ls i << 1 #define rs (i << 1) + 1 #define fi first #define se second #define CLR(a) while(!(a).empty()) a.pop() using namespace std; inline LL read() { LL s = 0,w = 1; char ch = getchar(); while(!isdigit(ch)) { if(ch == '-') w = -1; ch = getchar(); } while(isdigit(ch)) s = s * 10 + ch - '0',ch = getchar(); return s * w; } inline void write(LL x) { if(x < 0) putchar('-'), x = -x; if(x > 9) write(x / 10); putchar(x % 10 + '0'); } int a[110]; int dp[20000][110]; int main() { //#ifndef ONLINE_JUDGE // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); //#endif int n; scanf("%d",&n); int sum = 0; for(int i = 1;i <= n;++ i){ scanf("%d",&a[i]); sum += a[i]; } sum /= 2; for(int i = 1;i <= n;++ i) for(int j = sum;j >= a[i];-- j) for(int k = n / 2;k >= 1;-- k) dp[j][k] = max(dp[j][k],dp[j - a[i]][k - 1] + a[i]); printf("%d\n",dp[sum][n / 2]); return 0; }