0-1背包问题
一个容积为5的箱子,现在要装入物品,物品一共有4个,体积分别是1、2、3、4,问有几种填充方法。
这个问题很简单,一共有两种填充方法1、4和2、3,这里延伸一下:输入两个整数n和m,从数列1、2、3、4……、n中随意取几个数,使其和等于m,要求将其中所有可能的组合列出来,编程求解。
这里的算法一共有以下4步:
(1)比较n和m哪个大?如果n>m,则把m赋值给n。因为如果n>m,则那些m和n之间的数,是没有意义的。比如m=4,n=7,那么既然n中的5、6、7要比m大,所以是没有意义的。于是把m赋值给n,这样n也等于4,开始比较。
(2)现在我们开始填充箱子,先把体积最大的物品放入,看是否与箱子所剩容积相等。如果相等的话,则说明合适,打印物品。
(3)如果与箱子所剩容积不等,则用容积减去最大物品容积,看次大物品容积是否与箱子所剩容积相等,递归开始,直到物品全部比较完为止。
(4)这里要设计一个0-1背包:0代表没有装入物品,1代表装入该物品。比如一个容积为5的箱子,放入4,可以装入,则f[4] = 1,代表4是装入了,然后3、2,装不下,所以f[3] = f[2] = 0,1可以装入,则f[1] = 1。
源码实现:
#include<iostream>
#include<string>
using namespace std;
int mVal,nVal;
int *pOut;
void calFun(int m,int n)
{
if(m<1||n<1||(n==1&&m!=1))
return;
//看是否与箱子所剩容积相等
if(m==n)
{
pOut[n] = 1;
for(int i = 1;i<=nVal;++i)
{
if(pOut[i])
cout<<i<<" ";
}
cout<<endl;
pOut[n] = 0;
}
calFun(m,n-1);//不取n
pOut[n] = 1;
calFun(m-n,n-1);//取n
pOut[n] = 0;
}
int main()
{
cout<<"m:";
cin>>mVal;
cout<<"n:";
cin>>nVal;
pOut = new int[nVal+1];
memset(pOut,0,(nVal+1)*sizeof(int));
calFun(mVal,nVal);
delete []pOut;
return 0;
}
#include<string>
using namespace std;
int mVal,nVal;
int *pOut;
void calFun(int m,int n)
{
if(m<1||n<1||(n==1&&m!=1))
return;
//看是否与箱子所剩容积相等
if(m==n)
{
pOut[n] = 1;
for(int i = 1;i<=nVal;++i)
{
if(pOut[i])
cout<<i<<" ";
}
cout<<endl;
pOut[n] = 0;
}
calFun(m,n-1);//不取n
pOut[n] = 1;
calFun(m-n,n-1);//取n
pOut[n] = 0;
}
int main()
{
cout<<"m:";
cin>>mVal;
cout<<"n:";
cin>>nVal;
pOut = new int[nVal+1];
memset(pOut,0,(nVal+1)*sizeof(int));
calFun(mVal,nVal);
delete []pOut;
return 0;
}