题目链接:http://exam.upc.edu.cn/problem.php?id=3401
这个题综合了 排序和01背包 ,和ZOJ一题很像。
可能就是从ZOJ那里,这个题有一个问题,就是排序,01背包大家都懂。
排序成了这个题最核心的问题了。
原来我的想法是(x.a-(x.d*x.c))<(y.a-(y.d*y.c));
后来发现我的想法十分幼稚,因为这个只是单纯把一道题的价值最大化了,
但是这个题需要的排序,需要的全局最优,至于怎么实现,我是看了别人的博客才知道原来是怎么一回事。
就是把两个题目的先后顺序的最大化,
比如 先做第一题 (x.c)*x.d+(x.c+y.c)*y.d;
做第二题: (y.c)*y.d+(y.c+x.c)*x.d;
(x.c)*x.d+(x.c+y.c)*y.d < (y.c)*y.d+(y.c+x.c)*x.d 进行排序;
01背包注意,一定是过程中出现最大值,不一定是T的时候出现最大值。
贴上代码:
#include<bits/stdc++.h> using namespace std; int T,n,dp[1000400]={0}; typedef struct point{ int a,c,d; }point; point p[2020]; int cmp(point x,point y){ return x.c*x.d+(y.c+x.c)*y.d < y.c*y.d+(y.c+x.c)*x.d ; } int main() { scanf("%d%d",&n,&T); for(int i=0;i<n;i++){ scanf("%d",&p[i].a); }for(int i=0;i<n;i++){ scanf("%d",&p[i].d); }for(int i=0;i<n;i++){ scanf("%d",&p[i].c); } sort(p,p+n,cmp); memset(dp,0,sizeof(dp)); int maxz=-1; for(int i=0;i<n;i++){ for(int j=T;j>=p[i].c;j--){ dp[j]=max(dp[j],dp[j-p[i].c]+(p[i].a-p[i].d*(j))); maxz=max(maxz,dp[j]); } } /*for(int i=0;i<=T;i++){ printf("%d%c",dp[i],i==T?'\n':' '); }*/ printf("%d\n",maxz); return 0; }