ZOJ-3956 Course Selection System(01背包)

题意

n 门课程,每门课程都有它的快乐值 H i ,学分 C i 。现在选择若干门课程(可不选),它们的舒适值的结果满足下式:
( i m H x i ) 2 i m H x i i m C x i ( i m C x i ) 2
其中 x i 表示选择的第 i 门课的编号。求舒适值最大是多少。
1 n 500
1 H i 10000
1 C i 100

思路

首先令 H = i m H x i , C = i m C x i ,原式化简为 H 2 H C C 2
首先课程可以不选,那么原式小于等于零的情况可以不用考虑,而若原式大于零, H > C 是肯定的,再提取公因式得 H ( H C ) C 2 可见 C 一定时, H 值越大越有利,考虑到 C i 较小,可以将其作为背包的费用,01背包求出这个费用下 H 的最大值,再循环枚举所有可能的费用,求出舒适值的最大值。这其实很想枚举式子中一个变量,求另一个变量,但这里采用了01背包预处理另一变量。

代码

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
typedef long long LL;
using namespace std;
int dp[50003];

LL f(LL C,LL H){return H*H-H*C-C*C;}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,H[503],C[503],s=0;
        LL ans=0;
        memset(dp,-1,sizeof(dp));
        dp[0]=0;
        scanf("%d",&n);
        FOR(i,1,n)
        {   
            scanf("%d%d",&H[i],&C[i]);
            s+=C[i];
        }
        FOR(i,1,n)
            DOR(j,s,C[i])
                if(~dp[j-C[i]])
                    dp[j]=max(dp[j],dp[j-C[i]]+H[i]);
        FOR(i,0,s)if(~dp[i])ans=max(ans,f(i,dp[i]));
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/paulliant/article/details/80787950