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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

背包问题专栏(01,完全,多重)

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

本題的模板是套用了

A.S.KirigiriKyouko

的模板。請dalao見諒

一、01背包

有N件物品和一個容量為V的背包。第i件物品的價格(即體積,下同)是w[i],價值是c[i]。求解將哪些物品裝入背包可使這些物品的費用總和不超過背包容量,且價值總和最大。

這是最基礎的背包問題,總的來說就是:選還是不選,這是個問題<( ̄ˇ ̄)/

相當于用f[i][j]表示前i個背包裝入容量為v的背包中所可以獲得的最大價值。

對于一個物品,只有兩種情況

  情況一: 第i件不放進去,這時所得價值為:f[i-1][v]

  情況二: 第i件放進去,這時所得價值為:f[i-1][v-c[i]]+w[i]?

狀態轉移方程為:f[i][v] = max(f[i-1][v], f[i-1][v-w[i]]+c[i])

一道裸01背包題↓_↓

采藥

題目描述?Description

辰辰是個天資聰穎的孩子,他的夢想是成為世界上最偉大的醫師。為此,他想拜附近最有威望的醫師為師。醫師為了判斷他的資質,給他出了一個難題。醫師把他帶到一個到處都是草藥的山洞里對他說:“孩子,這個山洞里有一些不同的草藥,采每一株都需要一些時間,每一株也有它自身的價值。我會給你一段時間,在這段時間里,你可以采到一些草藥。如果你是一個聰明的孩子,你應該可以讓采到的草藥的總價值最大。”?

如果你是辰辰,你能完成這個任務嗎?

輸入描述?Input Description

輸入第一行有兩個整數T(1<=T<=1000)和M(1<=M<=100),用一個空格隔開,T代表總共能夠用來采藥的時間,M代表山洞里的草藥的數目。接下來的M行每行包括兩個在1到100之間(包括1和100)的整數,分別表示采摘某株草藥的時間和這株草藥的價值。

輸出描述?Output Description

輸出包括一行,這一行只包含一個整數,表示在規定的時間內,可以采到的草藥的最大總價值。

樣例輸入?Sample Input

70?3

71?100

69?1

1?2

樣例輸出?Sample Output

3

數據范圍及提示?Data Size & Hint

【數據規模】

對于30%的數據,M<=10;

對于全部的數據,M<=100。

//01背包問題 (采藥) //by Crazily #include<bits/stdc++.h> using namespace std; int w[105],v[105]; int dp[105][1005]; int main(){int t,m;scanf("%d%d",&t,&m);for(int i=1;i<=m;i++){scanf("%d%d",&w[i],&v[i]);}for(int i=1;i<=m;i++) for(int j=t;j>=0;j--){if(j>=w[i]){dp[i][j]=max(dp[i-1][j-w[i]]+v[i],dp[i-1][j]);} else{dp[i][j]=dp[i-1][j];} }printf("%d",dp[m][t]); }

再上一維的

#include<bits/stdc++.h> using namespace std; const int maxm = 2001, maxn = 101; int m, n; int w[maxn], c[maxn]; int f[maxm]; int main(){scanf("%d%d",&m, &n); //背包容量m和物品數量nfor (int i=1; i <= n; i++)scanf("%d%d",&w[i],&c[i]); //每個物品的重量和價值for (int i=1; i <= n; i++) //設f(v)表示重量不超過v公斤的最大價值for (int v = m; v >= w[i]; v--) //注意是逆序f[v] = max(f[v-w[i]]+c[i], f[v]);printf("%d\n",f[m]); // f(m)為最優解return 0; }

二、完全背包

有N種物品和一個容量為V的背包,每種物品都有無限件可用。第i種物品的費用是w[i],價值是c[i]。求解將哪些物品裝入背包可使這些物品的費用總和不超過背包容量,且價值總和最大。

完全背包和01背包十分相像, 區別就是完全背包物品有無限件。由之前的選或者不選轉變成了選或者不選,選幾件。√

和01背包一樣,我們可以寫出狀態轉移方程:f[i][v]=max(f[i-1][v-k*c[i]]+k*w[i]|0<=k*c[i]<=v)

還有一個簡單的優化↓_↓

當一個物品的價值小于另一個物品的價值,但是價格高于另一個物品,我們就可以不去考慮這個物品。即若兩件物品i、j滿足c[i]<=c[j]且w[i]>=w[j],則將物品j去掉,不用考慮。我們為什么要買一個又貴又難吃的東西呢(╯▽╰)

#include <iostream> #define V 500 using namespace std; int weight[20 + 1]; int value[20 + 1]; int f[V + 1]; int max(int a, int b) {return a > b ? a : b; } int main() {int n, m;cin >> n; for (int i = 1; i <= n; i++) {cin >> weight[i] >> value[i];}cin >> m;for (int i = 1; i <= n; i++) {for (int j = weight[i]; j <= m; j++) {f[j] = max(f[j], f[j - weight[i]] + value[i]);}}cout<< f[m] << endl; }

三、多重背包

有N種物品和一個容量為V的背包。第i種物品最多有n[i]件可用,每件費用是w[i],價值是c[i]。求解將哪些物品裝入背包可使這些物品的費用總和不超過背包容量,且價值總和最大。

這里又多了一個限制條件,每個物品規定了可用的次數。

同理,我們可以得出狀態轉移方程:f[i][v]=max(f[i-1][v-k*w[i]]+ k*c[i]|0<=k<=n[i])

一道例題↓_↓

慶功會

【問題描述】

為了慶賀班級在校運動會上取得全校第一名成績,班主任決定開一場慶功會,為此撥款購買獎品犒勞運動員。期望撥款金額能購買最大價值的獎品,可以補充他們的精力和體力。

【輸入格式】

第一行二個數n(n<=500),m(m<=6000),其中n代表希望購買的獎品的種數,m表示撥款金額。 接下來n行,每行3個數,v、w、s,分別表示第I種獎品的價格、價值(價格與價值是不同的概念)和購買的數量(買0件到s件均可),其中v<=100,w<=1000,s<=10。

【輸出格式】

第一行:一個數,表示此次購買能獲得的最大的價值(注意!不是價格)。

【輸入樣例】

5 1000

80 20 4

40 50 9

30 50 7

40 30 6

20 20 1

【輸出樣例】

1040

#include<stdio.h> #include<algorithm> using namespace std; int v[6002], w[6002], s[6002]; int f[6002]; int n, m; int main() {scanf("%d%d",&n,&m);for (int i = 1; i <= n; i++)scanf("%d%d%d",&v[i],&w[i],&s[i]);for (int i = 1; i <= n; i++)for (int j = m; j >= 0; j--)for (int k = 0; k <= s[i]; k++){if (j-k*v[i]<0) break;f[j] = max(f[j],f[j-k*v[i]]+k*w[i]);}printf("%d\n",f[m]);return 0; } //這是未優化的

再用二進制優化轉換成01

#include<stdio.h> #include<algorithm> using namespace std; int v[10001],w[10001]; int f[6001]; int n,m,n1; int main() {scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){int x,y,s,t=1;scanf("%d%d%d",&x,&y,&s);while (s>=t) {v[++n1]=x*t;w[n1]=y*t;s-=t;t*=2;}v[++n1]=x*s;w[n1]=y*s; //把s以2的指數分堆:1,2,4,…,2^(k-1),s-2^k+1, } for(int i=1;i<=n1;i++)for(int j=m;j>=v[i];j--)f[j]=max(f[j],f[j-v[i]]+w[i]); printf("%d\n",f[m]);return 0; }

//先借用一下dalao的代碼,有空我會慢慢碼上的

?

轉載于:https://www.cnblogs.com/crazily/p/9657725.html

總結

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

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