文章目录
前言
第4次发csdn,心情依旧是有些许的激动
购买项链问题
超市的柜台上成列着n条项链,每条项链都由若干颗珠宝串成。为了方便起见,我们使用不同的小写英文字母来表达不同的珠宝种类。
一位富豪希望从这些中挑选一些购买。但是他有一个奇怪的要求:把所有购买的项链上的珠宝全部汇集到一起后,每种珠宝的的个数都必须为偶数。现在他希望知道,一共有多少种购买方案(什么都不买也算作一种方案)能够满足这个要求?
Input
第一行,包含一个整数1<=n<=40,表示项链个数
接下来n行,每行包含一个长度不超过105 的字符串,代表项链
Output
输出一行整数,表示在满足富豪要求的前提下,购买方案的数量。
(进阶版:输出每种符合要求珠宝组合)
Example
input:
4
abc
bac
cbabc
abca
output:
4
分解题目问题
购买项链的问题可以分解为四个步骤:
1、记录店内所有项链
2、对店内所有项链进行排列组合
3、对项链组合中珠宝进行统计
4、输出符合要求组合个数
第一步:记录店内所有项链
用string数组给店内所有珠宝确定位置
*以下为部分代码,文章最后将给出完整程序
int num,G=1; //num珠宝数,G可选方案个数初始化为1(默认什么都不买)
cin>>num;
string STR[num]; //记录珠宝
for (int j=0;j<num;j++){ //
cin>>STR[j]; //
}
第二步:解决如何选取项链组合
用二进制比特序列解决选取问题,1代表选择该项链,0代表不选
例:
1001代表选择第一个和第四个项链
故我们需要生成比特序列
string group(int Size,int Num){ //将十进制数Num转换成比特序列
//返回序列长度为Size
string str;
if(Num==0){
for(int i=0;i<Size;i++){
str='0'+str;
}
return str;
}
while(Num!=1){
if(Num%2==1) str='1'+str;
else str='0'+str;
Num/=2;
}
str='1'+str;
int size1,size2;
size1=str.size();
if(size1<Size){
size2=Size-size1;
for(int i=0;i<size2;i++){
str='0'+str;
}
}
return str;
}
通过遍历即可得出所有排列方式
*为了方便统计珠宝个数,我们将每种组合的珠宝连成一条新的项链
*以下为部分代码,文章最后将给出完整程序
int Group; //总共组合方案个数
Group=pow(2,num); //2的num次方钟方案
for (int i=1;i<Group;i++){ //遍历每一种方案
string strG,strT; //strG为本次的组合类型,strT为本次选择的珠宝
strG=group(num,i);
for(int k=0;k<num;k++){ //用二进制中1代表选择,0代表不选
if(strG[k]=='1') strT+=STR[k];//将选择的项链连在一起变成新的项链
}
第三步:对项链组合中珠宝进行统计
我们从所得 新的项链 的第一个珠宝开始,将它与剩下的珠宝进行对比,若珠宝种类相同则该珠宝数目加一,然后将该位置标记为零
将数过的珠宝标记为零,下一次可以直接跳过
string strO; //strO为对比参数,其值为“000...0”,零的个数为Size
strO=group(Size,0);
while (strT!=strO) { //对新项链中每种珠宝进行计数
string one;
for(int r=0;r<Size;r++){ //从第一个珠宝开始,将其与之后的每个珠宝进行比较
if(strT[r]=='0') continue;
one=strT[r];
int num3=0;
for(int f=r;f<Size;f++){
if(one[0]==strT[f]){
num3++;
strT[f]='0'; //并将完成计数珠宝换成0
}
if((f+1)==Size && num3%2!=0){//若新项链中某珠宝个数为奇数,则这种排列方式不符合要求,故跳过
flag=1;
goto part1;
}
}
}
}
第四步:输出符合要求组合个数
cout<<"Number of combinations : "<<G; //输出可选个数
进阶版完整代码
#include <iostream>
#include <string>
#include<cmath>
using namespace std;
string group(int,int); //二进制解决排列组合
int main()
{
int num,G=1; //num珠宝数,G可选方案个数初始化为1(默认什么都不买)
cin>>num;
string STR[num]; //记录珠宝
for (int j=0;j<num;j++){ //
cin>>STR[j]; //
}
int Group; //总共组合方案个数
Group=pow(2,num); //2的num次方钟方案
for (int i=1;i<Group;i++){ //遍历每一种方案
string strG,strT; //strG为本次的组合类型,strT为本次选择的珠宝
strG=group(num,i);
for(int k=0;k<num;k++){ //用二进制中1代表选择,0代表不选
if(strG[k]=='1') strT+=STR[k];//将选择的项链连在一起变成新的项链
}
int Size,flag=0; //Size为组合成新项链的长度,flag为信标
Size=strT.size();
if(Size%2!=0) continue; //当项链长度为奇数时,必定不符合要求,故跳过
else {
string strO; //strO为对比参数,其值为“000...0”,零的个数为Size
strO=group(Size,0);
while (strT!=strO) { //对新项链中每种珠宝进行计数
string one;
for(int r=0;r<Size;r++){ //从第一个珠宝开始,将其与之后的每个珠宝进行比较
if(strT[r]=='0') continue;
one=strT[r];
int num3=0;
for(int f=r;f<Size;f++){
if(one[0]==strT[f]){
num3++;
strT[f]='0'; //并将完成计数珠宝换成0
}
if((f+1)==Size && num3%2!=0){//若新项链中某珠宝个数为奇数,则这种排列方式不符合要求,故跳过
flag=1;
goto part1;
}
}
}
}
}
part1:
G+=0;
if(flag==0) { //若该种组合符合要求,则输出组合方式
G++;
cout<<"*******************************"<<endl;
for(int k=0;k<num;k++){
if(strG[k]=='1') cout<<STR[k]<<endl;
}
cout<<"*******************************"<<endl;
}
}
cout<<"*******************************"<<endl;
cout<<"Not buy"<<endl;
cout<<"*******************************"<<endl;
cout<<""<<endl;
cout<<""<<endl;
cout<<""<<endl;
cout<<"Number of combinations : "<<G; //输出可选个数
return 0;
}
string group(int Size,int Num){
string str;
if(Num==0){
for(int i=0;i<Size;i++){
str='0'+str;
}
return str;
}
while(Num!=1){
if(Num%2==1) str='1'+str;
else str='0'+str;
Num/=2;
}
str='1'+str;
int size1,size2;
size1=str.size();
if(size1<Size){
size2=Size-size1;
for(int i=0;i<size2;i++){
str='0'+str;
}
}
return str;
}
以上为全部内容,祝你在学习道路上如履平地 ^_*