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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

动态规划--重拾我的“背包”

發布時間:2023/12/2 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 动态规划--重拾我的“背包” 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言:

  背包問題所涉及的是經典的動態規劃算法。因為長時間不AC了,漸漸感覺思維也都麻了!本文將基礎的背包問題做個小結,方便以后翻閱。感興趣的朋友也可以閱讀一下~
------------------------
(1)如何從n個重量和價值分別為Vi、Wi的物品中選擇一或多個放入最大容納量為S的背包使其總價值最大?

輸入:

5 10 ? (分別表示:n,S)
2 3
7 5
3 1
5 10
2 2

5 6
2 3
7 5
3 1
5 10
2 2

輸出:

15

10

分析:
f[i][j]:表示背包在存放了前i件物品占據j重量時的價值
其中,1<=i<=n,0<=j<=S;

當我到達某一個狀態,需要選擇是否將第i件物品放入我的背包時,必須考慮值不值的問題,即:
f[i][j] = max(f[i-1][j],f[i-1]][j-w[i]]+v[i]);

理解了上面的狀態轉移方程之后,就可以方便得出下面的偽代碼了:

  f[0...n][0...S] <- 0 //初始化
  for i<-1:n
    for j<-w[i]:S
      f[i][j] = max(f[i-1][j],f[i-1]][j-w[i]]+v[i]); //狀態轉移

代碼:

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=1e3+10; 6 int f[maxn][maxn]; 7 int main(){ 8 //數據從文件讀入 9 freopen("datain.txt","r",stdin); 10 int n,S,a,b; 11 while(scanf("%d%d",&n,&S)==2){ 12 memset(f,0,sizeof(f)); 13 for(int i=1;i<=n;i++){ 14 scanf("%d%d",&a,&b); 15 for(int v=1;v<=S;v++){ 16 if(v>=a) //do not neglect 'v<a' 17 f[i][v] = max(f[i-1][v],f[i-1][v-a]+b); 18 else 19 f[i][v] = f[i-1][v]; 20 } 21 } 22 printf("%d\n",f[n][S]); 23 } 24 return 0; 25 }

以上算法的時間復雜度、空間復雜度均為:O(n*S)

f[i][j]的變化過程:

-----------------------------

| ? 0 3 3 3 3 3 3 3 3 3 ? ? ? ? ? |

| ? 0 3 3 3 3 3 5 5 8 8 ? ? ? ? ? |
| ? 0 3 3 3 4 4 5 5 8 8 ? ? ? ? ? | ?
| ? 0 3 3 3 10 10 13 13 13 14 |
| ? 0 3 3 5 10 10 13 13 15 15 |

-----------------------------

?

在深入理解了狀態轉移方程之后,我們其實還可以對空間進行優化,僅用f[i]表示:背包質量達到i是獲得的價值。對應的偽代碼如下:

  f[0...S]<-0
  for i<-1:n
    for j<-S:w[i] //從右往左更新!
      f[j] = max(f[j],f[j-w[i]]+v[i]);

對空間進行優化后的代碼:

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=1e3+10; 6 int f[maxn]; 7 int main(){ 8 freopen("datain.txt","r",stdin); 9 int n,S,a,b; 10 while(scanf("%d%d",&n,&S)==2){ 11 memset(f,0,sizeof(f)); 12 for(int i=0;i<n;i++){ 13 scanf("%d%d",&a,&b); 14 for(int v=S;v>=a;v--){ 15 f[v] = max(f[v],f[v-a]+b); 16 } 17 } 18 printf("%d\n",f[S]); 19 } 20 return 0; 21 }

?

(2)如何從n個重量和價值分別為Vi、Wi的物品中選擇一或多個放入最大容納量為S的背包在背包剛好裝滿情況下,使其總價值最大?

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=1e3+10; 6 int f[maxn]; 7 int main(){ 8 freopen("datain.txt","r",stdin); 9 int n,S,a,b; 10 while(scanf("%d%d",&n,&S)==2){ 11 for(int i=1;i<=S;i++) f[i]=-0xfffffff; //最小的int 12 f[0]=0; 13 for(int i=0;i<n;i++){ 14 scanf("%d%d",&a,&b); 15 for(int v=S;v>=a;v--){ 16 f[v] = max(f[v],f[v-a]+b); 17 } 18 } 19 printf("%d\n",f[S]); 20 } 21 return 0; 22 } View Code

輸入:

5 10 ? (分別表示:n,S)
2 3
7 5
3 1
5 10
2 2

輸出:14

(3)如何從n種(每種無限個)重量和價值分別為Vi、Wi的物品中選擇一或多個放入最大容納量為S的背包使其總價值最大?

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=1e3+10; 6 int f[maxn]; 7 int main(){ 8 freopen("datain.txt","r",stdin); 9 int n,S,a,b; 10 while(scanf("%d%d",&n,&S)==2){ 11 memset(f,0,sizeof(f)); 12 for(int i=0;i<n;i++){ 13 scanf("%d%d",&a,&b); 14 for(int v=a;v<=S;v++){ 15 f[v] = max(f[v],f[v-a]+b); 16 } 17 } 18 printf("%d\n",f[S]); 19 } 20 return 0; 21 } View Code

輸入:

5 6
2 3
7 5
3 1
5 10
2 2

輸出:10

(4)如何從n種(每種無限個)重量和價值分別為Vi、Wi的物品中選擇一或多個放入最大容納量為S的背包在背包剛好裝滿情況下,使其總價值最大?

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=1e3+10; 6 int f[maxn]; 7 int main(){ 8 freopen("datain.txt","r",stdin); 9 int n,S,a,b; 10 while(scanf("%d%d",&n,&S)==2){ 11 for(int i=0;i<=S;i++) f[i]=-0xfffffff; 12 f[0]=0; 13 for(int i=0;i<n;i++){ 14 scanf("%d%d",&a,&b); 15 for(int v=a;v<=S;v++){ 16 f[v] = max(f[v],f[v-a]+b); 17 } 18 } 19 printf("%d\n",f[S]); 20 } 21 return 0; 22 } View Code

輸入:

5 6
2 3
7 5
3 1
5 10
2 2

輸出:9

----------------------------------------------
結語:
本文限于篇幅就只是對最最基本的01背包問題作了個人的分析,后面的3個擴展只貼代碼,希望感興趣的朋友們可以旁擊側敲吧~有問題或獨特見解的博友請留言~

轉載于:https://www.cnblogs.com/SeaSky0606/p/4743758.html

總結

以上是生活随笔為你收集整理的动态规划--重拾我的“背包”的全部內容,希望文章能夠幫你解決所遇到的問題。

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