0-1揹包問題
【問題描述】有n個重量分別爲{w1,w2,…,wn}的物品,它們的價值分別爲{v1,v2,…,vn},給定一個容量爲W的揹包。
設計從這些物品中選取一部分物品放入該揹包的方案,每個物品要麼選中要麼不選中,要求選中的物品不僅能夠放到揹包中,而且重量和爲W具有最大的價值。
即要確定x1、x2、…、xn的值( 0或1 ),使 w1,w2,…,wn £ W,且 v1x1+v2x2+…+vnxn 取得最大值。
f[i][j],其中i代表加入揹包的是前i件物品,j表示揹包的承重,f[i][j]表示當前狀態下能放進揹包裏面的物品的最大總價值。那麼,f[n][m]就是我們的最終結果了。
(1)假如我們放進揹包,f[i][j] = f[i - 1][j - weight[i]] + value[i],這裏的f[i - 1][j - weight[i]] + value[i]應該這麼理解:在沒放這件物品之前的狀態值加上要放進去這件物品的價值。
(2)假如我們不放進揹包,f[i][j] = f[i - 1][j]。
因此,我們的狀態轉移方程就是:f[i][j] = max(f[i][j] = f[i - 1][j] , f[i - 1][j - weight[i]] + value[i])
#include "pch.h"
#include <iostream>
#include<algorithm>
#define V 500
using namespace std;
int weight[20 + 1];
int value[20 + 1];
int f[20 + 1][V + 1];
int fk[20 + 1];
static int count = 0;
void trace(int n,int m){
if (n == 0) return;
//f[i][j] = max(f[i - 1][j], f[i - 1][j - weight[i]] + value[i]);
fk[n]= (f[n][m] == (f[n - 1][m - weight[n]] + value[n])?1 : 0);
f[n][m] != (f[n - 1][m - weight[n]] + value[n]) ? trace(n-1,m) : trace(n-1, m - weight[n]);
}
int main()
{
int n, m;
cout << "請輸入物品個數:";
cin >> n;
cout << "請分別輸入" << n << "個物品的重量和價值:" << endl;
for (int i = 1; i <= n; i++) {
cin >> weight[i] >> value[i];
}
cout << "請輸入揹包容量:";
cin >> m;
for (int i = 0; i <=n ; i++)
{
f[i][0] = 0;
}
for (int i = 0; i <= m; i++)
{
f[0][m] = 0;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (weight[i] > j) {
f[i][j] = f[i - 1][j];
}
else {
f[i][j] = max(f[i - 1][j], f[i - 1][j - weight[i]] + value[i]);
}
}
}
trace(n, m);
for (int i = 1; i <=n; i++)
{
cout << fk[i] << " ";
}
cout << "0/1揹包能放的最大價值爲:" << f[n][m] << endl;
}
完全揹包問題
【問題描述】有n種重量和價值分別爲wi、vi(1≤i≤n)的物品,從這些物品中挑選總重量不超過W的物品,求出挑選物品價值總和最大的挑選方案,這裏每種物品可以挑選任意多件。
#include <iostream>
#define V 500
using namespace std;
int weight[20 + 1];
int value[20 + 1];
int f[20 + 1][V + 1];
int fk[20 + 1][V + 1];
int main() {
int n, m;
cout << "請輸入物品個數:";
cin >> n;
cout << "請分別輸入" << n << "個物品的重量和價值:" << endl;
for (int i = 1; i <= n; i++) {
cin >> weight[i] >> value[i];
}
cout << "請輸入揹包容量:";
cin >> m;
for (i=1;i<=n;i++)
for (j=1;j<=m;j++)
{ if (j<weight[i])
f[i][j]=f[i-1][j];
else
f[i][j]=max(f[i-1][j],f[i][j-weight[i]]+value[i]);
}
cout << "揹包能放的最大價值爲:" << f[n][m] << endl;
}