author:sdgzyc++
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; }