一起来选课
题目地址:http://192.168.173.163/JudgeOnline/problem.php?cid=1019&pid=7
题目
明泽私立大学有n门课程提供给大一的同学来选课,每门课有两个数值来描述,开心程度Hi,复杂程度Ci。LW小太阳是个有奇怪癖好的人,假设他这学期要选m门课,把这m门课的Hi之和定义为sumH,Ci之和定义为sumC,并自己定义出本学期的课程舒适度为(sumH)2 - sumH * sumC - (sumC)2。
由于明泽私立大学是一所开放前卫的大学,它可以允许LW小太阳选择若干门课,使得他的课程舒适度最高(一门课都不选的时候,舒适度为0)
输入
2
3
10 1
5 1
2 10
2
1 10
2 10
输出
191
0
题解
01背包
因为n是500 c[i]是100,所以总共的sumC = 5e4 因此可以枚举每个sumC的出现情况,求得最大的sumH,然后更新答案。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define Max(a,b) (a>b?a:b)
const int N = 505;
int n, h[N], c[N];
// 记录最优答案
ll dp[N*100];
// 记录最优答案下的sumH
ll sumh[N*100];
int main()
{
// freopen("in.txt","r",stdin);
int T; scanf("%d", &T);
while(T--) {
scanf("%d", &n);
int mC =0;
for(int i = 1;i <= n; i++) {
scanf("%d %d", &h[i], &c[i]);
mC += c[i];
}
for(int i=0;i<=mC;i++)
dp[i] = sumh[i] = 0;
for(int i=1; i<=n; i++) {
for(int j=mC; j>=c[i]; j--) {
ll pre = j - c[i];
sumh[j] = max(sumh[j], sumh[pre] + h[i]);
}
}
/*
for(int i=1;i<=mC;i++) {
printf("%lld%c",sumh[i], i==mC? '
':' ');
}
for(int i=1;i<=mC;i++) {
printf("%lld%c",dp[i], i==mC? '
':' ');
}
*/
ll ans = 0;
for(int i=0;i<=mC;i++) {
// if(!dp[i]) continue;
ll mx = 1ll * sumh[i]*sumh[i] - 1ll*sumh[i]*i- i *i;
ans = Max(ans, mx);
}
printf("%lld
", ans);
}
return 0;
}