解題報告

author:sdgzyc++

6.12日

T1總感受是一個假題,T3推推式子看出單調性就沒了。
T2比較有意思:spa

題目大意:n個物品,屬性爲w,r,選擇第i件物品後,以後每選擇一個物品都會減去r的價值。
求按順序選擇物品的最大價值。code

solution:
考慮對於一個必須選擇的物品集合(大小爲n)
答案是:\(\sum w_i - \sum r_i * (n - i)\)
價值總和是\(\sum w_i\),是一個不變的值。
讓後面那個最小
即r從小到大排序便可。
這樣就把順序問題解決了。blog

那咱們能夠按照r從小到大的順序排序(這只是思路,寫法有待考慮)
沒有順序問題,只是單純的選擇物品就是一個揹包問題了。排序

結束上面的思考後。
讓r從小到大排序。
而後依次選擇:
轉移方程
dp[i][j]=max{dp[i-1][j],dp[i-1][j-1]+W[i]-R[i]*(j-1)}
如今碼力降低的很厲害。get

#include <bits/stdc++.h>
#define gc getchar()
using namespace std;
const int maxN = 3000 + 7;

inline int gi() {
    int x = 0,f = 1;char c = gc;
    while(c < '0' || c > '9') {if(c == '-')f = -1;c = gc;}
    while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = gc;}
    return x * f;
}

int f[maxN][maxN];

struct Node {
    int w , r;
}a[maxN];
bool cmp(Node a , Node b) {return a.r > b.r;}

int main() {
    int n = gi();
    for(int i = 1;i <= n;++ i) a[i].w = gi(),a[i].r = gi();
    sort(a + 1,a + n + 1,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] + a[i].w - a[i].r * (j - 1));
    int ans = 0;
    for(int i = 1;i <= n;++ i) ans = max(ans , f[n][i]);
    printf("%d",ans);
    return 0;
}

相關文章
相關標籤/搜索