(编程题)设有一个背包可以放入的物品的重量为s,现有n件物品,重量分别为w[1];w[2]; … ;w[n]。
问能否从这n件物品中选择若干件放入此背包中, 使得放入的重量之和正好为s。如果存在一种符合上诉要求的选择,
则称此背包问题有解(或称其解为真);否则称此背包问题无解(或称其解为假)。试用的递归方法
设计求解背包问题的算法。
思路:函数bool knapsack(s,w,n)在某次运算中存在4种情况
1)s<0 ,return false
2)s == 0,return true
3)s>0 && n<=0,return false
4)s>0 && n>0 又分2种情况
4.1)knapsack(s, w, n-1),第i个未被选中(递归,问题规模减小1)
4.2)knapsack(s-w[i],w,n-1),第i个被选中(递归,问题规模也减小1)
#include <iostream>
using namespace std;
bool knapsack(int s,int n, int w[]) {
if(s < 0)
return false;
if(s == 0)
return true;
if(s>0 && n<=0)
return false;
if(s>0 && n>0) {
int snew, wnew[100];
int i = 0;
//初始为-1
memset(wnew, -1, sizeof(wnew));
for(i=0; i<n; ++i) {
wnew[i] = w[i];
}
for(i=0; i<n; ++i) {
if(w[i] > 0) {
snew = s - w[i];
if(snew == 0)
return true;
else if( (n-1) > 0) {
bool ret;
//选i
//用-1标示已经选过,以后不可用
wnew[i] = -1;
ret = knapsack(snew, n-1, wnew);
if(ret)
return true;
//不选i
ret = knapsack(s, n-1,wnew);
if(ret)
return true;
}
}
}
}
return false;
}
int main() {
int s,n;
int * w;
cout << "Input s: "<<endl;
cin>>s;
cout <<"Input n: "<<endl;
cin >>n;
if(n <= 0) {
cout<<"n must bigger than 0"<<endl;
return 0;
}
w = new int[n];
int i = 0;
while(i < n) {
cout<<"Input w[" <<i<< "]:"<<endl; ;
cin>>w[i];
if(w[i] < 0) {
cout<<"w["<<i<<"] must bigger than 0"<<endl;
return 0;
}
else
++i;
}
bool ret = knapsack(s, n, w);
if(ret)
cout<<"ok"<<endl;
else
cout<<"fail"<<endl;
delete [ ]w;
return 0;
}