http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3956
题意:就是给你Hi,Ci的值,问怎么取使得下面那个式子的值最大:
理解:当时做了好久以为是贪心>_<.后来看别人的题解发现是01背包,现在学了01背包以后看就好理解多了。
因为每个值都是取或不取,所以容易想到是01背包。而且Hi的范围是[1,10000],Ci的范围是[1,100],n是[1,500],所以明显可以发现Ci适合做“物品体积”,Hi做“物品价值”,ΣCi做背包容量。由上式可知,若使式子的值越大,则ΣHxi越大越好,那么就01背包后判断一下就好。
这个背包想法很灵活,我刚开始就没明白为啥把Hi当做容量进行01背包。现在想想应该就是根据式子能得出ΣHxi越大越好,那么就需要用一种办法求得在条件内使得ΣHxi尽量最大化,所以想到01背包,把Hxi当做价值,那么自然ΣCi就应该当做背包容量,Ci当做体积,从数据范围也能看出这一点。背包完了之后,就依次判断当前容量为i(此时获得ΣHxi为f[i])时求得的上式的值,取个最大的就好。
参考代码:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; const int maxn=1000005; ll f[maxn]; int c[505],h[505]; int n; int main() { int T; scanf("%d",&T); while(T--){ memset(f,0,sizeof(f)); scanf("%d",&n); ll sum=0; for (int i=1;i<=n;i++){ scanf("%d%d",&h[i],&c[i]); sum+=c[i];//每次累加c[i],求得总共的背包容量 } for (int i=1;i<=n;i++){ for (int j=sum;j>=c[i];j--){ f[j]=max(f[j],f[j-c[i]]+h[i]);//一维滚动数组优化空间,求当前容量能装多少Hi。 } } ll ans=0; for (int i=1;i<=sum;i++){ ans=max(ans,f[i]*f[i]-f[i]*i-i*i);//求容量为i(ΣCxi),装了f[j](ΣHxi)这么多Hi时,式子的最大值。 } printf("%lld ",ans); } return 0; }