01背包问题
问题描述:
给定 n 件物品,物品的重量为 w[i],物品的价值为 v[i]。现挑选物品放入背包中,假定背包能承受的最大重量为 c,问应该如何选择装入背包中的物品,使得装入背包中物品的总价值最大?
- 纯递归
#include<iostream>
#include<algorithm>
using namespace std;
//01背包问题 纯递归
int w[] = {20,30,50};
int n = sizeof(w)/sizeof(w[0]);
int v[] = {5,10,25};
int c = 60;
int getMax(int i,int j){
if(i == 0)
return 0;
if(w[i] > j)
return getMax(i-1,j);
else
return max(getMax(i-1,j-w[i-1])+v[i-1],getMax(i-1,j));
}
int main()
{
cout<<getMax(n,c);
return 0;
}
- 递归+备忘录
备忘录方法是动态规划方法的变形。与动态规划算法不同的是,备忘录方法的递归方式是自顶向下的,而动态规划算法则是自底向上的。
- 动态规划
- 部分背包问题(可以选择物品i的一部分装入) 贪心算法
- 回溯法
- 分支限界法
#include <iostream>
#include <queue>
#include <string.h>
using namespace std;
//0-1背包问题 分支限界法(普通队列)
int V[3] = { 60, 100, 120 };
int W[3] = { 10, 20, 30 };
int n = 3;
int c = 50;
int bestvalue = 0; //220
int a[] = { 1, 2, 3, 4, 5,6 };
int x[6] = { 0 };
int n1 = 5;
class Node
{
public:
int x[3];
int t;
int w;
int v;
Node()
{
t = -1;
v = 0;
w = 0;
}
Node(Node &parent, int value)
{
t = parent.t + 1;
x[t] = value;
for (int i = 0; i < t; i++)
x[i] = parent.x[i];
w = parent.w + W[t] * value;
v = parent.v + V[t] * value;
}
void processOneSolution()
{
if (w <= c)
{
if (v > bestvalue)
bestvalue = v;
}
}
};
queue<Node> q; //普通队列
void branch()
{
Node rootnode;
q.push(rootnode);
while (!q.empty())
{
Node ext = q.front();
q.pop();
if (ext.t == n - 1)
{
ext.processOneSolution();
}
else
{
for (int i = 0; i < 2; i++)
{
Node son(ext, i);
q.push(son);
}
}
}
}
int main()
{
branch();
cout << bestvalue << endl;
system("pause");
return 0;
}