背包0-1问题不详细解释

 问题:输入两个整数n和m,从数列1,2,3,...,n中随意取几个数,使其和等于m,将其所有可能的组合列出来。

求解思路:

1.首先判断,如果n>m,则n中大于m的数不可能参与组合,此时置n=m;

2.将最大的数n加入且n==m,则满足条件,输出;

3.将n分两种情况求解:n没有加入,取n=n-1,m=m,递归;

4.n加入,取n=n-1,m=m-n,递归。

5.结束。

这个题是从欧立奇那个神经病的程序员面试宝典里面来的,程序写得相当简洁,一步到另一步怎么来的,写得特tm简单,看得我气得要死,单步跟踪也不知道tmd是怎么想出来的。我写个小小的注释,很明显,我还没有看懂。

 

#include <iostream>
#include <string>

using namespace std;

int mVal,nVal;
int *pOut;

//把体积为n的新木块装到体积为m的盒子里
void calFun(int m,int n)
{
 //盒子满了,或者最小的都塞不进去了,或者塞进去大了
 if(m<1||n<1||(n==1&&m!=1))
 {
  return;
 }

 //如果盒子剩余的空间和新木块的大小一样,也就是盒子满了
 if(m==n)
 {
  //n放进盒子里,m也满了,开始打印
  pOut[n]=1;
  for(int i=1;i<=nVal;++i)
  {
   if(pOut[i])
   {
    cout<<i<<" ";
   }
  }
  cout<<endl;
 }

    //把n放进盒子里的情况
 pOut[n]=1;
 //盒子剩余空间m-n,继续放n-1
 calFun(m-n,n-1);

 //不把n放盒子里的情况
    pOut[n]=0;
 //盒子剩余空间m,放n-1
 calFun(m,n-1);
}

int main(int argc,char* argv[])
{
 //输入和
 cout<<"m:";
 cin>>mVal;
 //输入待选数
 cout<<"n:";
 cin>>nVal;

 //筛选待选数
 if(mVal<nVal)
 {
  //n肯定比m小,因为比m大的数没有意义
  nVal=mVal;
 }

 //初始化被选标记都为0
 pOut=new int[nVal+1];
 memset(pOut,0,(nVal+1)*sizeof(int));
 calFun(mVal,nVal);
 delete []pOut;
 return 0;

}

 

posted on 2009-07-10 15:17  步走高飞  阅读(455)  评论(0编辑  收藏  举报

导航