cumtoj 一起来选课

一起来选课

题目地址: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? '\n':' ');
        }
        
        for(int i=1;i<=mC;i++) {
            printf("%lld%c",dp[i], i==mC? '\n':' ');
        }
        */ 
        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\n", ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Draymonder/p/10138959.html