ACM入门之【DP】
生活随笔
收集整理的這篇文章主要介紹了
ACM入门之【DP】
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
DP全稱動態(tài)規(guī)劃,是算法中的重中之重。
目錄
- 背包問題
- 01背包問題
- 完全背包
- 多重背包
- 分組背包
- 習(xí)題
- 線性DP
- 最長上升子序列
- 最長公共子序列
- 一個字符串修改后變成另一個字符串的最少步數(shù)
- 區(qū)間DP
- 計數(shù)類DP
- 狀態(tài)壓縮DP
- 樹形DP
- 記憶化搜索
背包問題
01背包: 每件物品最多只用一次
完全背包: 每件物品有無限個
多重背包 : 每件物品有不同多個
分組背包 : 有多個組,每組內(nèi)有多個物品,每一個組內(nèi)只能選一個
01背包問題
//f[i][j] 從前i個物品選,體積不超過j的最大價值 for(int i=1;i<=n;i++) {for(int j=0;j<=m;j++){f[i][j]=f[i-1][j];if(j>=v[i]) f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]);} } cout<<f[n][m]; //空間優(yōu)化的01背包 f[i] 表示體積不超過i的最大價值 for(int i=1;i<=n;i++) cin>>v[i]>>w[i]; for(int i=1;i<=n;i++) {for(int j=m;j>=v[i];j--){f[j]=max(f[j],f[j-v[i]]+w[i]);} } cout<<f[m];完全背包
for(int i=1;i<=n;i++) cin>>v[i]>>w[i]; for(int i=1;i<=n;i++) {for(int j=0;j<=m;j++){f[i][j]=f[i-1][j];f(j>=v[i]) f[i][j]=max(f[i][j],f[i][j-v[i]]+w[i]);} } cout<<f[n][m]<<endl; //空間優(yōu)化for(int i=1;i<=n;i++)for(int j=v[i];j<=m;j++)f[j]=max(f[j],f[j-v[i]]+w[i]); cout<<f[m]<<endl;多重背包
//暴力模板 for(int i=1;i<=n;i++) cin>>v[i]>>w[i]>>cnt[i];for(int i=1;i<=n;i++)for(int j=0;j<=m;j++)for(int k=0;k<=cnt[i]&&v[i]*k<=j;k++)f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]); cout<<f[n][m]; //二進(jìn)制優(yōu)化 #include<bits/stdc++.h> using namespace std; const int N=1e3*3+10; int f[N],v[N],w[N],cnt,n,m; int main(void) {cin>>n>>m;for(int i=0;i<n;i++){int v1,w1,c; cin>>v1>>w1>>c;int k=1;while(c>=k){++cnt;v[cnt]=v1*k,w[cnt]=w1*k;c-=k,k*=2;}if(c) {++cnt;v[cnt]=c*v1,w[cnt]=w1*c;}}for(int i=1;i<=cnt;i++){for(int j=m;j>=v[i];j--)f[j]=max(f[j],f[j-v[i]]+w[i]);}cout<<f[m];return 0; }分組背包
#include<bits/stdc++.h> using namespace std; const int N=1e3+10; int n,m,f[N][N],w[N][N],v[N][N],cnt[N]; int main(void) {cin>>n>>m;for(int i=1;i<=n;i++){cin>>cnt[i];for(int j=1;j<=cnt[i];j++) cin>>v[i][j]>>w[i][j];}for(int i=1;i<=n;i++){for(int j=0;j<=m;j++){f[i][j]=f[i-1][j];for(int k=1;k<=cnt[i];k++){if(j>=v[i][k]) f[i][j]=max(f[i][j],f[i-1][j-v[i][k]]+w[i][k]);}}}cout<<f[n][m];return 0; }習(xí)題
2. 01背包問題
3. 完全背包問題
4. 多重背包問題 I
5. 多重背包問題 II
9. 分組背包問題
線性DP
最長上升子序列
//樸素版 for(int i=0;i<n;i++) cin>>h[i]; for(int i=0;i<n;i++) {f[i]=1;for(int j=0;j<i;j++) if(h[j]<h[i]) f[i]=max(f[i],f[j]+1); } int res=0; for(int i=0;i<n;i++) res=max(res,f[i]); cout<<res; //二分+貪心優(yōu)化版 #include<bits/stdc++.h> using namespace std; const int N=1e5+10; int n,q[N],a[N],len; int main(void) {cin>>n;for(int i=0;i<n;i++) cin>>a[i];q[0]=-2*1e9;//哨兵for(int i=0;i<n;i++){int l=0,r=len;while(l<r){int mid=l+r+1>>1;if(q[mid]<a[i]) l=mid;else r=mid-1;}len=max(len,r+1);q[r+1]=a[i];}cout<<len;return 0; }最長公共子序列
#include<bits/stdc++.h> using namespace std; const int N=1e3+10; int f[N][N],n,m; char a[N],b[N]; int main(void) {cin>>n>>m>>a+1>>b+1;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(a[i]!=b[j]) f[i][j]=max(f[i][j-1],f[i-1][j]);else f[i][j]=max(f[i][j],f[i-1][j-1]+1);}}cout<<f[n][m]<<endl;return 0; }一個字符串修改后變成另一個字符串的最少步數(shù)
#include<bits/stdc++.h> using namespace std; const int N=1e3+10; int f[N][N],n,m; char a[N],b[N]; int main(void) {cin>>n>>a+1>>m>>b+1;for(int i=1;i<=n;i++) f[i][0]=i;for(int j=1;j<=m;j++) f[0][j]=j;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){f[i][j]=min(f[i-1][j]+1,f[i][j-1]+1);f[i][j]=min(f[i][j],f[i-1][j-1]+(a[i]!=b[j]));}}cout<<f[n][m]<<endl;//f[n][m]字符串a(chǎn)的前n個字符和字符串b的前m個字符相等需要的最小步數(shù)return 0; }區(qū)間DP
計數(shù)類DP
狀態(tài)壓縮DP
狀壓 dp 是動態(tài)規(guī)劃的一種,通過將狀態(tài)壓縮為整數(shù)來達(dá)到優(yōu)化轉(zhuǎn)移的目的。
樹形DP
記憶化搜索
《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的ACM入门之【DP】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ACM入门之【组合数】
- 下一篇: 91. 最短Hamilton路径【状压D