P2647 最大收益

Posted song-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2647 最大收益相关的知识,希望对你有一定的参考价值。

题目描述

现在你面前有n个物品,编号分别为1,2,3,……,n。你可以在这当中任意选择任意多个物品。其中第i个物品有两个属性Wi和Ri,当你选择了第i个物品后,你就可以获得Wi的收益;但是,你选择该物品以后选择的所有物品的收益都会减少Ri。现在请你求出,该选择哪些物品,并且该以什么样的顺序选取这些物品,才能使得自己获得的收益最大。

注意,收益的减少是会叠加的。比如,你选择了第i个物品,那么你就会获得了Wi的收益;然后你又选择了第j个物品,你又获得了Wj-Ri收益;之后你又选择了第k个物品,你又获得了Wk-Ri-Rj的收益;那么你获得的收益总和为Wi+(Wj-Ri)+(Wk-Ri-Rj)。

输入输出格式

输入格式:

 

第一行一个正整数n,表示物品的个数。

接下来第2行到第n+1行,每行两个正整数Wi和Ri,含义如题目所述。

 

输出格式:

 

输出仅一行,表示最大的收益。

 

输入输出样例

输入样例#1: 复制
2
5 2
3 5
输出样例#1: 复制
6

说明

20%的数据满足:n<=5,0<=Wi,Ri<=1000。

50%的数据满足:n<=15,0<=Wi,Ri<=1000。

100%的数据满足:n<=3000,0<=Wi,Ri<=200000。

样例解释:我们可以选择1号物品,获得了5点收益;之后我们再选择2号物品,获得3-2=1点收益。最后总的收益值为5+1=6。

正解:贪心+DP 100

注意:由于循环是正着来,而转移是倒着来,so :贪心应按照 r (对后面的影响) 从大到小排序,而非从小到大排序

  状态转移方程:F[i][j]=max{F[i-1][j],F[i-1][j-1]+w[i]+r[i]*(j-1)}

  边界条件:F[1][1]=w[1]  (可有可无,if从1开始循环)

技术分享图片
#include<bits/stdc++.h>
using namespace std;
int ans,n,f[3030][3030];
struct node{
    int w,r;
}mar[3030];
bool cmp(node A,node B){
    return A.r>B.r;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>mar[i].w>>mar[i].r;
    sort(mar+1,mar+1+n,cmp);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=i;j++){
            f[i][j]=max(f[i-1][j],f[i-1][j-1]+mar[i].w-mar[i].r*(j-1));//f[i][j] is i 判断了几个,j 选择了几个 
        } 
    }
    for(int i=1;i<=n;i++)
        ans=ans>f[n][i]?ans:f[n][i];
    cout<<ans;
    return 0;
}
View Code

暴力:DFS 50

技术分享图片
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<stack>
#include<iostream>
using namespace std;
int n,ans,vis[3030];
struct node{
    int w,r;
}coca[3030];
void init(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&coca[i].w,&coca[i].r);
}
void output(){
    printf("%d",ans);
}
void dfs(int sum,int hp,int sh){
    ans=ans>hp?ans:hp;
    if(sum==n) return ;
    for(int i=1;i<=n;i++){
        if(vis[i]==0){
            int tp=coca[i].w-sh;
            if(tp<0) continue;
            vis[i]=1;sum+=1;hp+=tp;sh+=coca[i].r;
            dfs(sum,hp,sh);
            vis[i]=0;sum-=1;hp-=tp;sh-=coca[i].r;
        }
    }
}
void work(){
    dfs(0,0,0);
}
int main()
{
    init();
    work();
    output();
    return 0;
}
View Code

 

以上是关于P2647 最大收益的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P2647 最大收益

洛谷—— P2647 最大收益

P2647 最大收益 (动态规划)

NC41 最长无重复子数组/NC133链表的奇偶重排/NC116把数字翻译成字符串/NC135 股票交易的最大收益/NC126换钱的最少货币数/NC45实现二叉树先序,中序和后序遍历(递归)(代码片段

计算收益最大回撤的思想和代码

收益回报与回报选择