旅行商的背包

洛咕

题意:有(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;
}

原文地址:https://www.cnblogs.com/PPXppx/p/11537336.html