1. 程式人生 > >P2647 最大收益

P2647 最大收益

put lose 狀態 獲得 ++ ont oca sed n)

題目描述

現在你面前有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 最大收益