CF (山东省赛-K题-排序+01背包)

题目链接: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;
}

猜你喜欢

转载自blog.csdn.net/z_sea/article/details/80289779
cf