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 }