ZOJ 3956 Course Selection System

题意

  有n节课可供选择,每节课都有两个值Hi和Ci,如果学生选择了m节课(x1,x2,....,xm),则它的舒适值被定义为:

  //这里没有公式((lll¬ω¬)),因为那个图片我保存不下来≧ ﹏ ≦,见原题好啦~

分析

  当时被这个公式搞得很懵逼,场上想了几种贪心发现都能找出反例。结束后听学长们说是个背包。。。一脸懵逼。

  我们在来看这个题···我们发现Ci比Hi小很多··这里算是一个暗示o(* ̄▽ ̄*)o

  我们再来看那个公式我们可以发现,当 C一定时,H越大这个舒适值越大。而对于每一节课我们都只有两种决策,选或者不选。那么我们就可以把这个问题转化为背包啦~

  我们定义f[i][j]=这个状态下最大的H值。我们按照背包的套路,把课作为阶段,把C定义为状态。

  那么转移也很显然

  f[i][j]=max(f[i-1][j],f[i-1][j-C[i]]+H[i])

  但是等等,这样提交并不能AC而是会Segmentation Fault,很懵逼,怎么改也不对。然后去查了题解,发现去要用滚动数组。ZOJ什么鬼啊!!这种情况不应该提示MLE之类的吗(雾~

  然后改一下滚动数组,代码比较短。

  

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 typedef long long LL;
 8 const int maxn=500+10;
 9 int T,n,M;
10 LL C[maxn],H[maxn];
11 LL f[50000+10];
12 
13 int main(){
14     scanf("%d",&T);
15     for(int t=1;t<=T;t++){
16         M=0;
17         scanf("%d",&n);
18         for(int i=1;i<=n;i++){
19             scanf("%d%d",&H[i],&C[i]);
20             M+=C[i];
21         }
22         memset(f,0,sizeof(f));
23         for(int i=1;i<=n;i++){
24             for(int j=M;j>=C[i];j--){
25                 f[j]=max(f[j],f[j-C[i]]+H[i]);
26             }
27         }
28         LL ans=0;
29         for(int i=0;i<=M;i++)
30             ans=max(ans,f[i]*f[i]-f[i]*i-i*i);
31         printf("%lld\n",ans);
32     }
33 return 0;
34 }
View Code

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324777050&siteId=291194637