日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ACM入门之【DP】

發布時間:2025/3/20 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ACM入门之【DP】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

DP全稱動態規劃,是算法中的重中之重。

目錄

  • 背包問題
    • 01背包問題
    • 完全背包
    • 多重背包
    • 分組背包
    • 習題
  • 線性DP
    • 最長上升子序列
    • 最長公共子序列
    • 一個字符串修改后變成另一個字符串的最少步數
  • 區間DP
  • 計數類DP
  • 狀態壓縮DP
  • 樹形DP
  • 記憶化搜索

背包問題


01背包: 每件物品最多只用一次

完全背包: 每件物品有無限個

多重背包 : 每件物品有不同多個

分組背包 : 有多個組,每組內有多個物品,每一個組內只能選一個


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]; //空間優化的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; //空間優化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]; //二進制優化 #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; }

習題

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; //二分+貪心優化版 #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; }

一個字符串修改后變成另一個字符串的最少步數

#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的前n個字符和字符串b的前m個字符相等需要的最小步數return 0; }

區間DP

計數類DP

狀態壓縮DP

狀壓 dp 是動態規劃的一種,通過將狀態壓縮為整數來達到優化轉移的目的。

樹形DP

記憶化搜索

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的ACM入门之【DP】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。