Gym - 101002H: Jewel Thief (背包,分組,DP決策單調性)
阿新 • • 發佈:2019-03-17
-s flow color row display left clas xmlns 決策
pro:給定N,M。輸入N個物品,(si,vi)表示第i個物品體積為si,價值為vi,s<=300,vi<=1e9; N<1e6;現在要求,對於背包體積為1到M時,求出最大背包價值。
sol:顯然直接跑背包會爆炸。 發現物品體積都比較小,我們先對相同體積的排序,對於體積相同的一起處理。
然後發現轉移都是在差為體積整數倍之間,按照容量對體積取模分組 ,發現組內部轉移滿足神奇的決策單調性。 然後就是s次分治。
O(K
#include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) #definerep2(i,a,b) for(int i=b;i>=a;i--) using namespace std; const int maxn=310; const int maxm=100010; ll dp[2][maxm]; vector<ll>G[maxn]; int x,d,t; void get(int L,int R,int l,int r) { if(L>R) return ; int Mid=(L+R)>>1,pos=Mid; for(int i=min(r,Mid-1);i>=l;i--){if(Mid-i>G[x].size()) break; if(dp[t][d+Mid*x]<dp[t^1][d+i*x]+G[x][Mid-i-1]){ pos=i; dp[t][d+Mid*x]=dp[t^1][d+i*x]+G[x][Mid-i-1]; } } get(L,Mid-1,l,pos); get(Mid+1,R,pos,r); } int main() { int N,M,s;ll v; scanf("%d%d",&N,&M); rep(i,1,N){ scanf("%d%lld",&s,&v); G[s].push_back(v); } rep(i,1,300){ if(G[i].size()==0) continue; sort(G[i].begin(),G[i].end(),greater<int>() ); for(int j=1;j<G[i].size();j++) G[i][j]+=G[i][j-1]; t^=1; rep(j,1,M) dp[t][j]=dp[t^1][j]; rep(j,0,i-1){ d=j; x=i; get(0,(M-j)/i,0,(M-j)/i); } rep(j,1,M) dp[t][j]=max(dp[t][j],dp[t][j-1]); } rep(i,1,M) printf("%lld ",dp[t][i]); return 0; }
Gym - 101002H: Jewel Thief (背包,分組,DP決策單調性)