zoukankan      html  css  js  c++  java
  • Luogu P2340 [USACO03FALL]Cow Exhibition G

    题面

    题意简述

    (n) 个物品,每个物品有两个属性(为整数),要求从中选若干个物品,使得两属性的总和最大且任意一个属性的和不得小于 (0)

    题意类似于背包,复杂度 (W = 400 imes 1000) 也符合 (O(nW)),就用背包的思想来考虑

    惯用伎俩,选一个属性为重量,另一个属性为价值,

    但是因为由负数重量的存在,所以在使用C++的时候就要将数组大小开到 (800000) ,下标 (400000) 代表重量为 (0)(400000) 以下是负数,以上是正数

    这样两个属性的和以及各自的和就能清晰算出了

    接下来就是做背包的问题了

    对于重量为正数的时候,与普通的01背包相同即可,由大到小更新

    对于重量为负数的时候,因为减去一个负数相当于加上一个正数,所以在做背包的时候要从最小向大更新

    核心代码:

        for(int i=1;i<=n;++i) {
            if(w[i]>=0) {                                            // 重量为正数
                for(int j=800000;j>=w[i];--j)                        // 从大往小枚举
                    f[j] = max(f[j],f[j-w[i]]+v[i]);
            } else {
                for(int j=0;j<=800000+w[i];++j) {                    // 重量为负数
                    f[j] = max(f[j],f[j-w[i]]+v[i]);                 // 从小往大枚举
                }
            }
        }
    

    最终答案就是

    [max_{400000leq i leq 800000} f_i+i-400000 (f_igeq 0) ]

    最终代码:

    #include<bits/stdc++.h>
    using namespace std;
    char ch;int fl;
    template<typename T>
    inline T redn(T &ret) {                                        // 快读
        ret=0,fl=1,ch=getchar();
        while(ch<'0' || ch>'9') {if(ch=='-')fl=-1;ch = getchar();}
        while(ch>='0'&&ch<='9') {ret=ret*10+ch-'0';ch=getchar();}
        return ret=ret*fl;
    }
    int n;
    int w[404],v[404],f[400000<<1+1];
    int main() {
        redn(n);
        for(int i=1;i<=n;++i) redn(w[i]),redn(v[i]);
        memset(f,128,sizeof f);
        f[400000] = 0;
        for(int i=1;i<=n;++i) {
            if(w[i]>=0) {                                            // 重量为正数
                for(int j=800000;j>=w[i];--j)                        // 从大往小枚举
                    f[j] = max(f[j],f[j-w[i]]+v[i]);
            } else {
                for(int j=0;j<=800000+w[i];++j) {                    // 重量为负数
                    f[j] = max(f[j],f[j-w[i]]+v[i]);                 // 从小往大枚举
                }
            }
        }
        int ans = 0;
        for(int i=400000;i<=800000;++i) if(f[i]>=0) ans = max(ans,f[i]+i-400000);
        printf("%d",ans);
    }
    
  • 相关阅读:
    苏教版国标本小学语文第一册汉字笔画
    C++ preprocessor __VA_ARGS__ number of arguments
    The Aggregate Magic Algorithms
    USB Mass Storage大容量存储的基本知识
    【转】驱动和应用层的三种通信方式
    Do You Actually Know What *P++ Does In C?
    Repeat Macro Cloak
    A SCSI command code quick reference
    USB device layout, descriptors, interface alternate setting
    RTOS Semaphore Services
  • 原文地址:https://www.cnblogs.com/Ax-Dea/p/12571609.html
Copyright © 2011-2022 走看看