Q:
小明假期同爸爸一起去书店,他选中了n本书,每本书的单价分别为:P1、P2、P3……Pn。不巧的是,小明的爸爸只带了M元钱,为了让小明渡过一个愉快的假期,爸爸仍然同意买书,但有一个要求,要小明从n本书中选出若干本,使得单价相加所得的和同M元最接近。你能够帮助小明解决这个问题吗?要求:总钱数M、书本数n以及各本书的价格从键盘或文件输入;如果有多种组合,应全部列出。
A:
解法①:利用二进制解决组合问题
按位与‘&’的计算规则:
两个数都为1时,才为1,否则为0;For example:
3&5=1; 3用二进制表达为 0011 ,5用二进制表达为 0101
0011
0101
=
0001 =2*0*1=1;
每本书有两种情况,买与不买,一共2*6-1=63种情况,除去都不买特殊的情景,从1~63均可用二进制表示,
在按位与运算解决组合问题;
Code:
#include<iostream>
using namespace std;
#define MAX 100
int main()
{
float price[MAX],sum=0,total,max=-1;
int i,j,n,a[MAX];
cout<<"Please enter the money of total"<<endl;
cin>>total;
cout<<"Please enter number of book"<<endl;
cin>>n; //输入书的种类
cout<<"please enter the price of book"<<endl;
for(i=0;i<n;++i)
cin>>price[i]; //分别输入每本书的价格
int m=1,k=1,count=0,pn;
for(j=1;j<n;++j)
{
m=2*m+1;
k<<=1; //k按位左移
}
for(i=1;i<=m;++i)
{
pn=0;
sum=0.0;
for(j=1;j<=k;j<<=1)
{
if((i&j)==j)
sum=sum+price[pn];
if(sum>total)
break;
pn++;
}
if(sum<=total)
{
if(sum>max)
{
count=1;
a[count-1]=i;
max=sum;
}
else if(sum==max)
{
count++;
a[count--]=i;
}
}
}
cout<<"there is"<<count<<" groups"<<endl;
for(i=0;i<count;++i)
{
pn=0;
for(j=1;j<=k;j<<=1)
{
if((a[i]&j)==j)
cout<<price[pn]<<" ";
pn++;
}
}
system("pause");
return 0;
}