動態規劃-揹包類
(一)01揹包
有個揹包,可以裝重為V的物品。有n種物品,第i個物品的重量(或說是空間)是v[i], 價值是c[i],每種物品只有一件,求能裝的最大價值
二維解法:
定義二維陣列f[i][j],表示前i件 重不超過j的物品的最大價值
動態轉移方程:(根據第i件物品取或不取)
f[i][j] = max(f[i-1][j], f[i-1][j-w[i]] + c[i]);
文字的解釋:
前i件重不超過j的物品的最大價值=取下面兩項之最優
1 f[i-1][j]表示前i-1件重j的物品的最大價值,也就是 第i件沒取,前i件的最大價值就是前i-1件的最大價值;
2 f[i-1][j-w[i]] + c[i] 表示前i-1件重j-w[i]的物品的最大價值 也就是第i件取了,佔了w[i]的重量,增加了c[i]的價值
解是 f[n][V] (前n個物品重不超過V的最大價值)
#include <iostream>
using namespace std;
int n, V;
int v[200], c[200];
int f[1001][1001]; // f[i][j] --> 前i個物品,重量不超過j的最大價值
int main() {
cin >> V >> n;
for(int i=1; i<=n; i++) cin >> v[i] >> c[i];
for(int i=1; i<=n; i++) { //迴圈前i件物品
for(int j=V; j>0; j--) { //迴圈重量j
if(v[i] <= j) f[i][j] = max(f[i-1][j], f[i-1][j-v[i]] + c[i]);
else f[i][j] = f[i-1][j]; //放不下
}
}
cout << f[n][V] << endl;
return 0;
}
一維解法:
定義陣列f[j], 表示重不超過j的物品的最大價值
動態轉移方程:(根據第i件物品取或不取)
f[j] = max(f[j], f[j-w[i]] + c[i]);
j迴圈必須是j=V...0
#include <iostream>
using namespace std;
int n, V;
int v[200], c[200];
int f[1001]; // f[j] --> 重量不超過j的最大價值
int main() {
cin >> V >> n;
for(int i=1; i<=n; i++) cin >> v[i] >> c[i];
for(int i=1; i<=n; i++) { //迴圈前i件物品
for(int j=V; j>=v[i]; j--) { //迴圈重量j (j<v[i]時放不下,不操作)
f[j] = max(f[j], f[j-v[i]] + c[i]);
}
}
cout << f[V] << endl;
return 0;
}
(二)完全揹包
有個揹包,可以裝重為V的物品。有n種物品,第i個物品的重量是v[i], 價值是c[i],
每種物品有無限件,求能裝的最大價值
一維解法:
定義陣列f[j], 表示重不超過j的物品的最大價值
動態轉移方程:同01揹包一維解法一樣(根據第i件物品取或不取)
f[j] = max(f[j], f[j-w[i]] + c[i]);
與01不同的是:
j迴圈必須是j=0...V
重不超過j的物品的最大價值
解是f[V](重量不超過V的最大價值)
#include <iostream>
using namespace std;
int n, V;
int v[200], c[200];
int f[1001]; // f[j] --> 重量不超過j的最大價值
int main() {
cin >> V >> n;
for(int i=1; i<=n; i++) cin >> v[i] >> c[i];
for(int i=1; i<=n; i++) { //迴圈前i件物品
for(int j=v[i]; j<=V; j++) { //迴圈重量j (j<v[i]時放不下,不操作)
f[j] = max(f[j], f[j-v[i]] + c[i]);
}
}
cout << f[V] << endl;
return 0;
}
(三)多重揹包
有個揹包,可以裝重為V的物品。有n種物品,第i個物品的重量是v[i], 價值是c[i],
每種物品有s[i]件,求能裝的最大價值
一維解法:
定義陣列f[j], 表示重不超過j的物品的最大價值
動態轉移方程:(根據第i件物品取或不取)
i=1...n;
j=V...0;
k=0...s[i] //K迴圈件數s[i]
f[j] = max(f[j], f[j-w[i]*k] + c[i]*k);
(多重揹包與01揹包一樣:j迴圈是j=0...V)
解是f[V];
#include <iostream>
using namespace std;
int n, V;
int v[200], c[200], s[200];
int f[1001]; // f[j] --> 前需要佔重量不超過j的最大價值
int main() {
cin >> V >> n;
for(int i=1; i<=n; i++) cin >> v[i] >> c[i] >> s[i];
for(int i=1; i<=n; i++) {
for(int j=V; j>=0; j--) {
for(int k=0; k<=s[i]; k++) {
if(j-v[i]*k < 0) break; //k是遞增的,揹包不夠k迴圈結束
f[j] = max(f[j], f[j-v[i]*k] + c[i]*k);
}
}
}
cout << f[V] << endl;
return 0;
}
(四)混合揹包
有個揹包,可以裝重為V的物品。有n種物品,第i個物品的重量是v[i], 價值是c[i],
有的物品有1件,有的有s[i]件,有的有無限件,求能裝的最大價值
解法:
i=1...n;
if(第i件是完全揹包) ..
else if(第i件是多重揹包) ..
//只能取1件作為s[i]為1的物品
可以根據混合情況變通if語句
三種揹包-混合揹包:
#include <iostream>
using namespace std;
int n, V;
int v[1001], s[1001], c[1001];
int f[1001];
int main() {
cin >> V >> n;
for(int i=1; i<=n; i++) cin >> v[i] >> c[i] >> s[i];
for(int i=1; i<=n; i++) {
if(s[i] == 0) {
for(int j=v[i]; j<=V; j++)
f[j] = max(f[j], f[j-v[i]]+c[i]);
} else {
for(int j=V; j>=v[i]; j--)
for(int k=1; k<=s[i]; k++) {
if(j >= k * v[i]) {
f[j] = max(f[j], f[j - k * v[i]] + k * c[i]);
} else break;
}
}
}
cout << f[V] << endl;
return 0;
}
(五)二維費用揹包
二維費用只是直接在原有揹包上加一維度和迴圈
1原來f[j]表示V不超過j的最大價值
現在f[j][k]表示V1不超過j且V2不超過k的最大價值
2 原來f[j] = max(f[j],f[j-v[i]] + c[i]);
現在f[j][k] = max(f[j][k], f[j-v1[i]][k-v2[i]] + c[i]);
這樣連三維費用揹包都會了..
這裡直接是二維費用的混合三種揹包:
#include <iostream>
using namespace std;
int n, V1, V2;
int v1[1001], v2[1001], m[1001], c[1001];
int f[1001][1001];
int main() {
cin >> n >> V1 >> V2;
for(int i=1; i<=n; i++) cin >> v1[i] >> v2[i] >> m[i] >> c[i];
for(int i=1; i<=n; i++) {
if(m[i] == 0) { //如果第i件是完全揹包
for(int j=v1[i]; j<=V1; j++) {
for(int k=v2[i]; k<=V2; k++) {
f[j][k] = max(f[j][k], f[j-v1[i]][k-v2[i]] + c[i]);
}
}
} else { //如果第i件數量有限(01或多重)
for(int j=V1; j>=v1[i]; j--) {
for(int k=V2; k>=v2[i]; k--) {
for(int s=1; s<=m[i]; s++) {
if(j - s*v1[i] < 0 || k - s*v2[i] < 0) break;
f[j][k] = max(f[j][k], f[j-v1[i]*s][k-v2[i]*s] + c[i]*s);
}
}
}
}
}
cout << f[V1][V2] << endl;
return 0;
}
(六)有依賴性的揹包
【金明的預算方案】
【解法】分五種情況處理主件:不取,只取主件,取主件和附件1,取主件和附件2,取主件和兩個附件.找最優情況
#include <iostream>
using namespace std;
int V, n, num; //V是金錢,n是物品總數,num記錄主件數
int v[61][4]; //v[i][0]記錄有幾個附件了,v[i][1]:主件的價格,v[i][2]:附件1,v[i][3]:附件2
int p[61][4]; //同上,記錄重要度
int f[61][32001]; //f[i][j]表示前i件主件價格為j的最大價值
int map[61]; //i對映到v、p陣列(num)
int main() {
int tmpv, tmpp, follow;
cin >> V >> n;
for(int i=1; i<=n; i++) {
cin >> tmpv >> tmpp >> follow;
if(follow == 0) {
v[++num][1] = tmpv;
p[num][1] = tmpp;
map[i] = num;
continue;
}
follow = map[follow];
v[follow][++v[follow][0]+1] = tmpv;
p[follow][++p[follow][0]+1] = tmpp;
}
for(int i=1; i<=num; i++) {
for(int j=1; j<=V; j++) {
f[i][j] = f[i-1][j];
if(j >= v[i][1]) f[i][j] = max(f[i][j], f[i-1][j-v[i][1]]+v[i][1]*p[i][1]);
if(j >= v[i][1]+v[i][2]) f[i][j] = max(f[i][j], f[i-1][j-v[i][1]-v[i][2]]+v[i][1]*p[i][1]+v[i][2]*p[i][2]);
if(j >= v[i][1]+v[i][3]) f[i][j] = max(f[i][j], f[i-1][j-v[i][1]-v[i][3]]+v[i][1]*p[i][1]+v[i][3]*p[i][3]);
if(j >= v[i][1]+v[i][2]+v[i][3]) f[i][j] = max(f[i][j], f[i-1][j-v[i][1]-v[i][2]-v[i][3]]+v[i][1]*p[i][1]+v[i][2]*p[i][2]+v[i][3]*p[i][3]);
}
}
cout << f[num][V] << endl;
return 0;
}
(七)分組揹包
N件物品,第i個物品的重量是v[i], 價值是c[i],每個物品有自己的組,每組只能選一個物品,求能裝的最大價值
(可以看下原題 洛谷-分組揹包)#include <iostream>
using namespace std;
int v[200][1010], c[200][1010];
int F[1010];
int V, N, G;
int main() {
int v1, c1, opt;
cin >> V >> N;
for(int i=1; i<=N; i++) {
cin >> v1 >> c1 >> opt;
G = max(G, opt);
v[opt][++v[opt][0]] = v1;
c[opt][++c[opt][0]] = c1;
}
for(int i=1; i<=G; i++)
for(int j=V; j>=0; j--)
for(int k=1; k<=v[G][0]; k++)
if(j >= v[i][k])
F[j] = max(F[j], F[j-v[i][k]] + c[i][k]);
cout << F[V] << endl;
return 0;
}
QWQ,就這樣了...#end
相關文章
- 揹包問題----動態規劃動態規劃
- 【動態規劃】揹包問題動態規劃
- 動態規劃 01揹包問題動態規劃
- 【動態規劃】01揹包問題動態規劃
- 動態規劃-01揹包問題動態規劃
- 動態規劃篇——揹包問題動態規劃
- 動態規劃0-1揹包動態規劃
- 動態規劃--01揹包問題動態規劃
- 【動態規劃】01揹包問題【續】動態規劃
- 演算法-動態規劃-完全揹包演算法動態規劃
- 01揹包動態規劃空間優化動態規劃優化
- 0-1揹包問題(動態規劃)動態規劃
- 多重揹包動態規劃及空間優化動態規劃優化
- 動態規劃之0,1揹包問題動態規劃
- 動態規劃系列之六01揹包問題動態規劃
- 動態規劃解0-1揹包問題動態規劃
- 0-1揹包問題 動態規劃法動態規劃
- 01揹包問題理解動態規劃演算法動態規劃演算法
- 動態規劃-揹包01問題推理與實踐動態規劃
- 【動態規劃】一次搞定三種揹包問題動態規劃
- 動態規劃之 0-1 揹包問題詳解動態規劃
- 詳解動態規劃01揹包問題--JavaScript實現動態規劃JavaScript
- 詳解動態規劃01揹包問題–JavaScript實現動態規劃JavaScript
- 雙核處理(動態規劃的01揹包問題)動態規劃
- 【動態規劃】0-1揹包問題原理和實現動態規劃
- python 動態規劃(揹包問題和最長公共子串)Python動態規劃
- 動態規劃之01揹包問題(最易理解的講解)動態規劃
- DP 動態規劃 Problem V 1022 反向考慮的揹包動態規劃
- 前端與演算法-動態規劃之01揹包問題淺析與實現前端演算法動態規劃
- 洛谷 1064——金明的預算方案(動態規劃的揹包問題)動態規劃
- 【動態規劃(一)】動態規劃基礎動態規劃
- 揹包問題演算法全解析:動態規劃和貪心演算法詳解演算法動態規劃
- [資料結構與演算法]-動態規劃之揹包演算法終極版資料結構演算法動態規劃
- 【演算法資料結構Java實現】Java實現動態規劃(揹包問題)演算法資料結構Java動態規劃
- 【LeetCode動態規劃#08】完全揹包問題實戰與分析(零錢兌換II)LeetCode動態規劃
- 動態規劃動態規劃
- 動態規劃分類題目總結動態規劃
- 【LeetCode動態規劃#06】分割等和子集(01揹包問題一維寫法實戰)LeetCode動態規劃