您的位置:首页 > 产品设计 > UI/UE

Value【NOIP2016提高A组模拟8.17】

2016-08-17 21:54 459 查看

题目



样例输入:



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(fi−1,j,fi−1,j−1+v[i]−w[i]∗(j−1))

时间复杂度: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
[i],ans);
printf("%d",ans);
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  背包