0
点赞
收藏
分享

微信扫一扫

牛客 - WY15 幸运的袋子(DFS)

奋斗De奶爸 2022-04-30 阅读 59

牛客

 

                 

解题思路:

          每次从全集中选择若干元素(小球)组成子集(袋子)。 对于任意两个正整数a,b如果满足 a+b>ab,则必有 一个数为1.可用数论证明:设a=1+x,b=1+y,则1+x+1+y>(1+x)(1+y),---> 1>xy,则xy必有一个为0,即a,b 有一个为1. 推广到任意k个正整数,假设a1,a2,...ak,如果不满足给定条件,即和sum小于等于积pi。如果此时再选择一个数b,能使其满足sum+b > pib,则,b必然为1,且为必要非充分条件。反之,如果选择的b>1,则 sum+b <= pi*b,即a1,a2,...,ak,b不满足给定条件。

        因此,将球按标号升序排序。每次从小到大选择,当选择到a1,a2,...,ak-1时满足给定条件,而再增加选择ak 时不满足条件(ak必然大于等于max(a1,a2,...,ak-1)),继续向后选择更大的数,必然无法满足!此时不必再继续向后搜索。 如果有多个1,即当k=1时,sum(1)>pi(1)不满足,但下一个元素仍为1,则可以满足 1+1>1*1, 所以要判断当前ak是否等于1,如果等于1,虽然不能满足,组合的个数不能增加,但是继续向后 搜索 仍然有满足条件的可能 .对于重复数字,组合只能算一个,要去重.

                

代码:

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

int Solution(vector<int>& ans , int n , int pos , int sum ,int mul)
{
    int count = 0 ;
    for(int i = pos;i < n ;++i)
    {
        sum += ans[i];
        mul *= ans[i];
        
        if(sum > mul)
        {
             count += 1 + Solution(ans,n,i+1,sum,mul);
        }
        else if(ans[i] == 1) //连续的1
        {
            count += Solution(ans , n ,i+1 , sum , mul);
        }
        else //因为是有序的,只要后面一个不成立,后面的都不成立
        {
            break;
        }
        
        //回溯
        sum -= ans[i];
        mul /= ans[i];
        
        
        //对于重复数字,组合只能算一个,要去重
        while(i < n-1 && ans[i] == ans[i+1]) 
        {
            i++;
        }  
    }
    
    return count;
}

int main()
{
    int n;
    cin>>n;
    vector<int> ans(n);
    
    for(int i = 0 ; i < n ; i++)
    {
        cin>>ans[i];
    }
    
    sort(ans.begin() , ans.end()); //使序列升序
    cout << Solution(ans, n, 0 , 0 , 1)<<endl;
    
    return 0;
}

举报

相关推荐

0 条评论