ZOJ - 3956 -- Course Selection System -- 01背包变形
Description
There are n courses in the course selection system of Marjar University. The i-th course is described by two values: happiness Hi and credit Ci. If a student selects m courses x1, x2, ..., xm, then his comfort level of the semester can be defined as follows:
Edward, a student in Marjar University, wants to select some courses (also he can select no courses, then his comfort level is 0) to maximize his comfort level. Can you help him?
Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line contains a integer n (1 ≤ n ≤ 500) -- the number of cources.
Each of the next n lines contains two integers Hi and Ci (1 ≤ Hi ≤ 10000, 1 ≤ Ci ≤ 100).
It is guaranteed that the sum of all n does not exceed 5000.
We kindly remind you that this problem contains large I/O file, so it's recommended to use a faster I/O method. For example, you can use scanf/printf instead of cin/cout in C++.
OutputFor each case, you should output one integer denoting the maximum comfort.
Sample Input2 3 10 1 5 1 2 10 2 1 10 2 10Sample Output
191
0
Hint
For the first case, Edward should select the first and second courses.
For the second case, Edward should select no courses.
题意:
一个学生选课,每选则一门课程,他有 happiness Hi and credit Ci。另外,他的 comfort level 计算方式如上,算出他选课可以获得的最大的comfort level。
思路:
根据以上的计算公式可以知道,要保证选课学生的 comfort level最大,只要在一定的 Credit 的情况下,让 Happiness 最大就可以了。
因此可以将输入的所有的 credit 相加后的总和作为 包的大小。让 Happiness 作为包中装物品的价值。
动态转移方程为:
dp[j] = max(dp[j],dp[j-C[i]] + H[i]);
j表示的是 credit ; dp[j] 表示在credit为 j 的时候,Happiness 的最大值
代码:
#include <cstdio> #include <iostream> #include <algorithm> #include <vector> #include <cstring> #define LL long long #define maxn 60000 #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; int H[maxn]; int C[maxn]; LL dp[maxn]; int main() { int n,t; scanf("%d",&t); while(t--){ int sumC = 0; mem(dp,0); scanf("%d",&n); for(int i = 1;i <= n;i++){ scanf("%d%d",&H[i],&C[i]); sumC+=C[i]; } for(int i = 1;i <= n;i++){ for(int j = sumC;j >= C[i];j--){ dp[j] = max(dp[j],dp[j-C[i]]+H[i]); } } LL ans = 0; for(int i = 0;i <= sumC;i++){ ans = max(ans,dp[i]*dp[i]-dp[i]*i-i*i); } printf("%lld\n",ans); } return 0; }
//最终的结果需要为 long long 类型的数值,WA了一次