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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

动态规划(冬令营课堂笔记)

發布時間:2023/12/10 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 动态规划(冬令营课堂笔记) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

簡單問題

  01背包

  012背包

  部分背包

  機器分配

  烽火傳遞

  花店櫥窗問題

簡單問題

01背包

一個容量為m的背包,有n個物品,第i個物品的體積為wi,價值為ci。選擇若干物品,使得體積總和不超過m的情況下價值總和最大。

n<=100,m<=10000。

?

搜索? 復雜度為2^n

void dfs(int x,int y,int z)//當前物品編號,當前容量,當前價值 {if(x==n+1){if(y<m)ans=max(ans,z);return;}dfs(x+1,y+w[x],z+c[i]);dfs(x+1,y,z); }

如果前兩維相同,只需選擇第三維的最大值

小小的變形

const int INF=0x7f; int dfs(int x,int y) {int ans;if(x==n+1){if(y>m)return -INF;return 0;}ans=max(dfs(x+1,y+w[x])+c[x],dfs(x+1,y));return ans; } dfs(1,0);

加一個數組記錄

const int INF=0x7f; int dfs(int x,int y) {if(x==n+1){if(y>m)return -INF;return 0;}dp[x][y]=max(dfs(x+1,y+w[x])+c[x],dfs(x+1,y));return dp[x][y]; } dfs(1,0);

應用記錄狀態? 記憶化搜索 n*m

const int INF=0x7f; int dfs(int x,int y) {if(y>m)return -INF;if(x==n+1){return 0;}if(dp[x+1][y+w[x]]) //選該物品 dp[x][y]=max(dp[x+1][y+w[x]]+c[x],dp[x][y]);elsedp[x][y]=max(dfs(x+1,y+w[x])+c[x],dp[x][y]); if(dp[x+1][y]) //不選該物品 dp[x][y]=max(dp[x+1][y]+c[x],dp[x][y]);elsedp[x][y]=max(dfs(x+1,y))+c[x],dp[x][y]); return dp[x][y]; } dfs(1,0);

遞歸變遞推

先寫出搜索

最大/最小值 存放到數組中

后面遞歸該狀態時 直接使用數組中的值來代替

O(dfs里的狀態個數*轉移的時間復雜度)

?

找邊界

找遞推方法(順序還是逆序)

轉移(推轉移方程)

搜索->記憶化搜索->遞歸變遞推

for(int i=n;i>=1;i--)for(int j=0;j<=m;j++)dp[i][j]=max(dp[i+1][j],dp[i+1][j+w[i]]+c[i]); ans=dp[1][0]

012背包

一個容量為m的背包,有n個物品,第i個物品的體積為wi,價值為ci,有2個。

選擇若干物品,使得體積總和不超過m的情況下價值總和最大。

記憶化搜索

const int INF=0x7f; int dfs(int x,int y,int z) {if(x==n+1){if(y<m)ans=max(ans,z);return -INF;}if(dp[x+1][y]) //一個都不選 dp[x][y]=max(dp[x][y],dp[x+1][y]);elsedp[x][y]=max(dp[x][y],dfs(x+1,y));if(dp[x+1][y+w[x]]) //選一個 dp[x][y]=max(dp[x][y],dp[x+1][y+w[x]])+c[x]);elsedp[x][y]=max(dp[x][y],dfs(x+1,y+w[x])+c[x]);if(dp[x+1][y+w[x]]) //選兩個 dp[x][y]=max(dp[x][y],dp[x+1][y+2*w[x]])+2*c[x]);elsedp[x][y]=max(dp[x][y],dfs(x+1,y+2*w[x])+2*c[x]);return dp[x][y]; } dfs(1,0);

部分背包

一個容量為m的背包,有n個物品,第i個物品的體積為wi,價值為ci,有ki個。

選擇若干物品,使得體積總和不超過m的情況下價值總和最大。

記憶化搜索

int dfs(int x,int y) {if (y>m) return -INF;if (x==n+1) return 0;for (int i=0; i<=k[x]; i++){if (dp[x+1][y+i*w[x]])dp[x][y]=max(dp[x][y],dp[x+1][y+i*w[x]]+c[x]);elsedp[x][y]=max(dp[x][y],dfs(x+1,y+i*w[x])+i*c[x]);}return dp[x][y]; } dfs(1,0);

遞推

for (i=n; i>=1; i--)for (j=0; j<=m; j++)for (l=0; l<=k[i]; l++)dp[i][j]=max(dp[i][j],dp[i+1][j+l*w[i]]+l*c[i]); dp[1][0]

機器分配

有n家店,每家店都有m臺機器,第i家店購買j臺機器花費a[i][j]元(可能存在a[i][j]>a[i][j+1]),要購買總共m臺機器,求最小花費。

搜索

//機器分配 dfs(int x,int y,int z) {if(y>m)return;if(x==n+1){if(y==n+1)ans=min(ans,z);return;}for(int i=0;i<=m;i++)dfs(x+1;y+i,z+a[x][i]); } dfs(1,0,0);

小小的變形

//機器分配 int dfs(int x,int y) {if(y>m)return -INF;if(x==n+1){if(y==m)return 0;//再也不需要買機器 return -INF;}for(int i=0;i<=m;i++)dp[x][y]=min(dp[x][y],dfs(x+1,y+i)+a[x][i]);return dp[x][y]; } dfs(1,0);

記憶化搜索

//機器分配 int dfs(int x,int y) {if(y>m)return -INF;if(x==n+1){if(y==m)return 0;//再也不需要買機器 return -INF;}for(int i=0;i<=m;i++)if(dp[x+1][y+i])dp[x][y]=min(dp[x][y],dp[x+1][y+i]+a[x][i]);elsedp[x][y]=min(dp[x][y],dfs(x+1,y+i)+a[x][i]);return dp[x][y]; } dfs(1,0);

遞推

for(int i=n;i>=1;i--)for(int j=0;j<=m;j++){dp[i][j]=INF;for(k=0;k<=m-j;k++)dp[i][j]=min(dp[i][j],dp[i+1][j+k]+a[i][k]);} ans=dp[1][0]

烽火傳遞

給定n個非負整數,選擇其中若干數字,使得每連續k個數中至少有一個數被選出。

要求選擇的數字之和盡可能小。

搜索

void dfs(int x,int y) {if(x==n+1){ans=min(ans,y);return;}for(int i=x+1;i<=min(n+1,x+k);i++)dfs(i,y+a[i]);//i是下一個 } dfs(0,0);

記憶化

int dfs(int x) {if(x==n+1)return 0;dp[x]=INF;for(int i=x+1;i<=min(n+1,x+k);i++)if(dp[i])dp[x]=min(dp[x],dp[i]+a[i]);elsedp[x]=min(dp[x],dfs(i)+a[i]);return dp[x]; } dfs(0);

遞推

/*dp[n+1]=0; dp[1] dp[2] dp[3] .. dp[1+k]*/for (i=n; i>=0; i--) {dp[i]=INF;for (int j=i+1; j<=min(n+1,i+k); j++)dp[i]=min(dp[i],dp[j]+a[j]); } dp[0]

花店櫥窗問題

給定一個n*m的矩陣A(n<=m),求一個序列a1,a2,…,an滿足1<=a1<a2<…<an<=m。使得A[1][a1]+A[2][a2]+…+A[n][an]最大。A可能有負數。

搜索

void dfs(int x,int y,int z) {if(x==n+1){if(y==m+1)ans=max(ans,z);return;}for(int i=y+1;i<=m;i++)dfs(x+1,i,z+a[x+1][i]); } dfs(0,0,0);

記憶化搜索

int dfs(int x,int y) {if(x==n+1){if(y==m+1)return 0;else return -INF;}for(int i=y+1;i<=m;i++){if(dp[x+1][i])dp[x][y]=max(dp[x][y],dp[x+1][i]+a[x+1][i]);elsedp[x][y]=max(dp[x][y],dfs(x+1,i)+a[x+1][i]);return dp[x][y];} } dfs(0,0);

遞推

/*dp[n+1][m+1]=0; dp[n+1][0~m]=-INF; dp[1][] dp[2][] dp[3][]*/ for (i=n; i>=0;i--)for (j=0; j<=m+1; j++)for (k=j+1; k<=m+1; k++)dp[i][j]=max(dp[i][j],dp[i+1][k]+a[i+1][k]); cout<<dp[0][0];

?

轉載于:https://www.cnblogs.com/thmyl/p/7359328.html

總結

以上是生活随笔為你收集整理的动态规划(冬令营课堂笔记)的全部內容,希望文章能夠幫你解決所遇到的問題。

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