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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

DP——背包问题(一)

發布時間:2023/12/20 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 DP——背包问题(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 以前不是很重視 DP ,遇到 DP 就寫貪心、暴搜……其實這是非常錯誤的,現在開始練習 DP 了才發現,我好菜……

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 對于DP的整理,先從眾所周知的背包問題開始。

———————— 01背包:n 個物品,重量和價值分別為 w[i]、v[i],背包容量 W,求所有挑選方案中價值總和的最大值。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?DP 方程 :dp[j] = max ( dp[j] , dp[ j - w[i] ] + v[i] ) ,其中 dp[j]為使用 j 的容量獲得的最大價值,i 為第 i 件物品。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?代碼:

1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 #include<string> 7 using namespace std; 8 int n,W,w[2000],v[2000],dp[2000]; 9 int main(){ 10 scanf("%d %d",&n,&W); 11 for(int i=1;i<=n;i++) scanf("%d %d",&w[i],&v[i]); 12 for(int i=1;i<=n;i++) 13 for(int j=W;j>=w[i];j--){ 14 dp[j]=max(dp[j],dp[j-w[i]]+v[i]); 15 } 16 printf("%d",dp[W]); 17 return 0; 18 } 01背包

?

———————— 完全背包:n 種物品,數目不限,其他的和 01背包 一 樣。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?DP 方程 : dp[j] = max ( dp[j] , dp[ j - w[i] + v[i] ) ,是不是感覺和 01背包 一樣?其實,就是 一樣……-- ^ --|||||,但代碼有細微差別……

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?代碼:

1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 #include<string> 7 using namespace std; 8 int n,W,w[2000],v[2000],dp[2000]; 9 int main(){ 10 scanf("%d %d",&n,&W); 11 for(int i=1;i<=n;i++) scanf("%d %d",&w[i],&v[i]); 12 for(int i=1;i<=n;i++) 13 for(int j=w[i];j<=W;j++){ 14 dp[j]=max(dp[j],dp[j-w[i]]+v[i]); 15 } 16 printf("%d",dp[W]); 17 return 0; 18 } 完全背包


? ? ? ? ? ? ? ? ? ? ? ? ? ? 那么,問題來了,為什么 01背包 是倒著 循環,而 完全背包 是正著循環……動筆模擬一下,你會發現且理解 — 正著循環會對一件物品重復選取╮(╯_╰)╭,而倒著循環就不會……

?

————————?多重背包:n 種物品,給定數目 m[i],其他和 01 背包一樣。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?DP 方程:dp[j] =max ( dp[j],dp[ j - w[i] ] + v[i] ),&%&……¥怎么又一樣,其實 多重背包 就是特殊處理化的 01背包,這個特殊處理就是 二進制拆分。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?二進制拆分:眾所周知什么是二進制,二進制拆分就是把 m[i] 個物品拆成 1個物品、2個物品組成的新物品、4個物品組成的新物品、8個物品組成的新物品……一 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?直到不能拆為止,因為二進制可以 表示 出任何實數的嘛。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?代碼:

1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 #include<string> 7 using namespace std; 8 int n,W,w[2000],v[2000],dp[2000],m[2000]; 9 int main(){ 10 scanf("%d %d",&n,&W); 11 int x=n; 12 int y; 13 for(int i=1;i<=n;i++) scanf("%d %d %d",&w[i],&v[i],&m[i]); 14 for(int i=1;i<=x;i++){ 15 y=1; 16 while(m[i]>y&&m[i]>1){ 17 n++; 18 w[n]=y*w[i]; 19 v[n]=y*v[i]; 20 m[i]-=y; 21 y=y*2; 22 } 23 w[i]=m[i]*w[i]; 24 v[i]=m[i]*v[i]; 25 } 26 for(int i=1;i<=n;i++) 27 for(int j=W;j>=w[i];j--){ 28 dp[j]=max(dp[j],dp[j-w[i]]+v[i]); 29 } 30 printf("%d",dp[W]); 31 return 0; 32 } 多重背包

?

———————— 三種混合背包(01背包、完全背包、多重背包):這種問題就是給定 m[i],若 m[i] 為 -1,則為數目無限,否則數目有限,其他的和 01背包 一樣。雖然寫著是三種 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?混合背包,但我認為實際上是兩種背包,多重背包 和 完全背包。方法就是能拆分的就拆分,在循環的時候,判斷一下,如果是 完全背包 就正著循環,不然就倒 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?著循環…………蠻easy的QAQ~

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?代碼:

1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 #include<string> 7 using namespace std; 8 int n,W,w[2000],v[2000],dp[2000],m[2000]; 9 int main(){ 10 scanf("%d %d",&n,&W); 11 int x=n; 12 int y; 13 for(int i=1;i<=n;i++) scanf("%d %d %d",&w[i],&v[i],&m[i]); 14 for(int i=1;i<=x;i++) if(m[i]!=-1) { 15 y=1; 16 while(m[i]>y&&m[i]>1){ 17 n++; 18 w[n]=y*w[i]; 19 v[n]=y*v[i]; 20 m[i]-=y; 21 y=y*2; 22 } 23 w[i]=m[i]*w[i]; 24 v[i]=m[i]*v[i]; 25 } 26 for(int i=1;i<=n;i++) 27 if(m[i]!=-1) 28 for(int j=W;j>=w[i];j--){ 29 dp[j]=max(dp[j],dp[j-w[i]]+v[i]); 30 } 31 else 32 for(int j=w[i];j<=W;j++) 33 dp[j]=max(dp[j],dp[j-w[i]]+v[i]); 34 printf("%d",dp[W]); 35 return 0; 36 } 混合背包

轉載于:https://www.cnblogs.com/Misaki-Mei/p/7347556.html

總結

以上是生活随笔為你收集整理的DP——背包问题(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

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