揹包問題 DP
阿新 • • 發佈:2021-07-28
各種各樣的基礎揹包
\(0-1\) 揹包
非常樸素,複雜度 \(O(nV)\)
void z_o_pack(int c,int v)
{
for(int i=V;i>=c;i--)
dp[i]=max(dp[i],dp[i-c]+v);
}
完全揹包
複雜度 \(O(nV)\)
void comp_pack(int c,int v)
{
for(int i=c;i<=V;i++)
dp[i]=max(dp[i],dp[i-c]+v);
}
多重揹包
這裡的寫的是單調佇列優化的多重揹包。
複雜度可以達到 \(nV\)
int ql,qr; struct QUE { int num,val; }que[Maxv]; void many_pack(int c,int w,int m) { if(!c) { add+=m*w; return; } m=min(m,V/c); for(int pos=0,s;pos<c;pos++) { ql=1,qr=0,s=(V-pos)/c; for(int j=0;j<=s;j++) { while(ql<=qr && que[qr].val<=(dp[pos+j*c]-j*w)) qr--; que[++qr]=(QUE){j,dp[pos+j*c]-j*w}; while(ql<=qr && (j-que[ql].num)>m) ql++; dp[pos+j*c]=max(dp[pos+j*c],que[ql].val+j*w); } } }
樹形依賴揹包
複雜度:\(O(n^2)\)
雖然有三層迴圈,但是內層運算總量與整棵子樹內點對個數一致。
void dfs(int x) { siz[x]=1,dp[x][1]=w[x]; for(int i=hea[x];i;i=nex[i]) { dfs(ver[i]); siz[x]+=siz[ver[i]]; for(int j=min(siz[x],V+1);j>=2;j--) for(int k=1;j-k>=1;k++) dp[x][j]=max(dp[x][j],dp[ver[i]][k]+dp[x][j-k]); } }