zoukankan      html  css  js  c++  java
  • 旅行商的背包

    洛咕

    题意:有(n)种物品,第(i)种体积为(V_i),价值为(W_i),共有(D_i)件.的背包体积是(C).还有m件奇货,第(i)件的价值(Y_i)与分配的体积(X_i)之间的关系为(Y_i=a_i*X_i^2+b_i*X_i+c_i).求最大价值.(1≤n,C≤10000,1≤m≤5,1≤Wi,Vi,Di≤1000,-1000≤ai,bi,ci≤1000.)

    分析:前面n种物品是多重背包来做,二进制优化或者单调队列优化都可以.后面m件物品是完全背包,直接枚举分配的体积就好了.

    无力吐槽这道题.自己的单调队列优化多重背包怎么都T两个点,别人的跑得飞快.

    把自己的辣鸡80分代码也挂出来吧,希望引以为戒.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    #define rg register
    using namespace std;
    inline int read(){
        rg int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=10005;
    int q[N],f[2][N];
    inline int maxx(int a,int b){if(a>b)return a;return b;}
    int main(){
    	rg int n=read(),m=read(),C=read();
    	for(rg int i=1;i<=n;++i){
    		rg int v=read(),w=read(),d=read();
    		for(rg int j=0;j<v;++j){
    			rg int l=1,r=0;
    			for(rg int k=j;k<=C;k+=v){
    				while(l<=r&&k-q[l]>v*d)++l;
    				while(l<=r&&f[(i-1)&1][q[r]]-q[r]/v*w<f[(i-1)&1][k]-k/v*w)--r;
    				q[++r]=k;
    				f[i&1][k]=f[(i-1)&1][q[l]]+(k-q[l])/v*w;
    			}
    		}
    	}
    	for(rg int i=1;i<=m;++i){
    		rg int a=read(),b=read(),c=read();
    		for(rg int j=C;j>=0;--j)
    			for(rg int k=0;k<=j;++k)
    				f[n&1][j]=maxx(f[n&1][j],f[n&1][j-k]+a*k*k+b*k+c);		
    	}
    	printf("%d
    ",f[n&1][C]);
        return 0;
    }
    

    题解代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    #define rg register
    using namespace std;
    inline int read(){
        rg int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=1e4+5;
    int dp[N],f[N],q[N];
    int main(){
    	rg int n=read(),m=read(),C=read();
    	for(rg int i=1;i<=n;++i){
    		rg int v=read(),w=read(),d=read();
    		for(rg int j=0;j<v;++j){
    			rg int l=1,r=0;
    			for(rg int k=0;k*v+j<=C;++k){
    				rg int x=dp[k*v+j]-k*w;
    				while(l<=r&&x>f[r])--r;
    				q[++r]=k;f[r]=x;
    				if(q[l]+d<k)++l;
    				dp[k*v+j]=f[l]+k*w;
    			}
    		}
    	}
    	for(rg int i=1;i<=m;++i){
    		rg int a=read(),b=read(),c=read();
    		for(rg int j=C;j>=0;--j)
    			for(rg int k=0;k<=j;++k)
    				if(dp[j-k]+(a*k+b)*k+c>dp[j])dp[j]=dp[j-k]+(a*k+b)*k+c;
    	}
    	printf("%d
    ",dp[C]);
        return 0;
    }
    
    
  • 相关阅读:
    康复计划
    Leetcode 08.02 迷路的机器人 缓存加回溯
    Leetcode 38 外观数列
    Leetcode 801 使序列递增的最小交换次数
    Leetcode 1143 最长公共子序列
    Leetcode 11 盛水最多的容器 贪心算法
    Leetcode 1186 删除一次得到子数组最大和
    Leetcode 300 最长上升子序列
    Leetcode95 不同的二叉搜索树II 精致的分治
    Leetcode 1367 二叉树中的列表 DFS
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11537336.html
Copyright © 2011-2022 走看看