• ZOJ 3956 Course Selection System [01背包]


    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3956

    题意:就是给你Hi,Ci的值,问怎么取使得下面那个式子的值最大:

      $$(sum_{i=1}^{m} H_{x_i})^2-(sum_{i=1}^{m} H_{x_i})	imes(sum_{i=1}^{m} C_{x_i})-(sum_{i=1}^{m} C_{x_i})^2$$

    理解:当时做了好久以为是贪心>_<.后来看别人的题解发现是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;
    }
  • 相关阅读:
    主流的Nosql数据库的对比
    CCF考试真题题解
    排序
    2017-10-03-afternoon
    POJ——T 2728 Desert King
    51Nod——T 1686 第K大区间
    POJ——T 2976 Dropping tests
    2017-10-02-afternoon
    入参是小数的String,返回小数乘以100的String
    银联支付踩过的坑
  • 原文地址:https://www.cnblogs.com/zxhyxiao/p/6937168.html
Copyright © 2020-2023  润新知