Value【NOIP2016提高A组模拟8.17】

来源:互联网 发布:mac系统怎样翻墙 编辑:程序博客网 时间:2024/05/18 18:01

题目

这里写图片描述
样例输入:
这里写图片描述
5
8 2
10 7
5 1
11 8
13 3

样例输出:
这里写图片描述
27

数据范围:
这里写图片描述


剖解题目

被虐,不想说了QwQ~~


思路

其实是因为在前几天做过一道类似的题目,所以自然而然就往背包dp方面去想,因为考虑到这个w会造成后效性,就试着证明些东西。结果后来的dp打错了QAQ~~
详细可见“疯狂的火神”这道题。


解法

40%:暴力。时间复杂度:O(n!).
100%:对于一个确定的顺序,他的最优值也是确定的。
假设我们选i,j,k这三件物品,那么我们会获得的价值val1=v[i]+v[j]-w[i]+v[k]-w[i]-w[j]。若我们交换其中两项,如顺序改为i,k,j,我们获得价值是val2=v[i]+v[k]-w[i]+v[j]-w[i]-w[k];我们设val1>val2,则化简后有w[j]< w[k],也就是说我们要先选w小的,排个序就好。
按照w大到小排序,然后就是一个背包dp了。设fi,j表示选择前i个物体中,选择最后j个物体能获得最大价值,转移就很容易了。

fi,j=max(fi1,j,fi1,j1+v[i]w[i](j1))

时间复杂度:O(n2).


代码

#include<cstdio>#include<algorithm>#include<cstdlib>#include<cstring>#define fo(i,a,b) for(int i=a;i<=b;i++)using namespace std;const int maxn=5005;int n,f[maxn][maxn];struct cy{    int v,w;}a[maxn];bool cmp(cy a,cy b){    return a.w>b.w;}int main(){    scanf("%d",&n);    fo(i,1,n) scanf("%d%d",&a[i].v,&a[i].w);    sort(a+1,a+n+1,cmp);    fo(i,1,n){        fo(j,1,i) f[i][j]=max(f[i-1][j],f[i-1][j-1]+a[i].v-a[i].w*(j-1));    }    int ans=0;    fo(i,1,n) ans=max(f[n][i],ans);    printf("%d",ans);}

这里写图片描述

0 0
原创粉丝点击