1. 程式人生 > >cumtoj 一起來選課

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;
}