思路:这道题就是找数组中的子集 ,乍一看没有思路,这道题可以用树的结构画图,用递归思想解决这道题。
这里有一个条件,如果想要和大于积,组合的数里面必须有一个数字1,这样才会存在和大于积,但不一定每个都是。我们要对这个数组排序,这样才能更好的组合。
那么在组合的过程中,遇到不是幸运的组合,需要将它跳过,跟下一个数进行组合,因为已经和这个不是幸运数字组合的数加或乘了,所以要将他回溯,把它减或除到上一个数的组合,这样才能跳过这个数,与下一个数重新组合。比如112356这个数组,当1 1 2 3和5组合不是幸运组合,因为我们已经将5这个数加和乘了,所以要回溯,减和除,将它变为1123再与6组合。
这之中很有可能出现重复的组合,需要去重。
#include <iostream>
#include <vector>
#include <algorithm>//sort头文件
using namespace std;
int GetLuckyPacket(vector<int>& x,int n,int pos,int sum,int multi)
{
int count=0;
for(int i=pos;i<n;i++)
{
sum+=x[i];
multi*=x[i];
if(sum>multi)
count+=1+GetLuckyPacket(x,n,i+1,sum,multi);//继续加/乘第i+1位置的数
else if(x[i]==1)//因为组合中必须有1,所以遇到1,不用count+1,直接递归加或乘i+1位置的数
count+=GetLuckyPacket(x,n,i+1,sum,multi);
else
break;//如果上面两个条件都不成立,直接跳出循环语句
//回溯,走到这里要么是上面两个条件不成立,幸运组合不成立;要么就是走到循环最后了,需要返回递归的值
sum-=x[i];
multi/=x[i];
//去重,上两个条件不成立(不是1,sum<multi),判断当前数字和此后的数字是不是重复的,因为此数字已经组不成幸运组合,那么它的重复数字都是无效的
while(i<n-1 && x[i]==x[i+1])
{
i++;
}
}
return count;
}
int main()
{
int n;
while(cin>>n)
{
vector<int> x(n);//初始化n个空间,初始值都是0,相当于vector<int> x(n,0);
for(int i=0;i<n;++i)
{
cin>>x[i];
}
sort(x.begin(),x.end());//vector直接用迭代器,如果定义数组,直接用下标
int count=GetLuckyPacket(x,n,0,0,1);//数组,个数,起始位置,加初始值,乘初始值
cout<<count<<endl;
}
return 0;
}