0/1背包的求解方案
01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的体积为W1,W2至Wn,与之相对应的价值为P1,P2至Pn。01背包是背包问题中最简单的问题。01背包的约束条件是给定几种物品,每种物品有且只有一个,并且有权值和体积两个属性。在01背包问题中,因为每种物品只有一个,对于每个物品只需要考虑选与不选两种情况。如果不选择将其放入背包中,则不需要处理。如果选择将其放入背包中,由于不清楚之前放入的物品占据了多大的空间,需要枚举将这个物品放入背包后可能占据背包空间的所有情况。
#include <iostream>
#include <vector>
using namespace std;
//求1-n的幂集
vector<vector<int> >ps;
void PSet(int n) {
vector<vector<int> >ps1;
vector<int> s;
ps.push_back(s);
vector < vector<int>>::iterator it;
for (int i = 1; i <= n;i++) {
ps1 = ps;
for (it = ps1.begin(); it != ps1.end();++it) {
(*it).push_back(i);
}
for (it = ps1.begin(); it != ps1.end();++it) {
ps.push_back(*it);
}
}
}
void Knap(int w[],int v[],int W) {
int count = 1; //方案编号
int sumw, sumv; //当前方案的总重量和总价值
int maxi, maxsumw = 0, maxsumv = 0; //最佳方案的编号、总重量和总价值
vector<vector<int> >::iterator it; //幂集迭代器
vector<int>::iterator its; //幂集集合元素迭代器
cout << "编号" <<"\t"<< "选中物品" << "\t" << "总重量" << "\t" << "总价值" << "\t" << "能否装入" << endl;
for (it = ps.begin(); it != ps.end();++it) { //扫描ps中的每一个集合元素
cout << count << "\t";
sumw = 0, sumv = 0;
cout << "{";
for (its = (*it).begin(); its != (*it).end();++its) {
cout << (*its);
sumw += w[*its-1]; //w数组下标从0开始
sumv += v[*its - 1]; //v数组下标从0开始
}
cout << "}"<<"\t\t";
cout << sumw << "\t" << sumv << "\t";
if (sumw<=W) {
cout << "能"<<endl;
if (sumv> maxsumv) { //比较求最优方案
maxsumv = sumv;
maxsumw = sumw;
maxi = count;
}
}
else {
cout << "不能"<<endl;
}
count++; //方案编号增加1
}
cout << endl;
cout << "最佳方案为";
cout << "选中物品";
cout << "{";
for (its = ps[maxi].begin(); its != ps[maxi].end();++its) {
cout << *its;
}
cout << "}";
cout << "总重量为" << maxsumw << "," << "总价值为:" << maxsumv << endl;
}
int main() {
int n = 4, W = 6;
int w[] = { 5,3,2,1 };
int v[] = { 4,4,3,1 };
PSet(n);//找出所有的组合
cout << "0/1背包的求解方案为:" << endl;
Knap(w,v,W);
return 0;
}