2017校招真题在线编程-幸运的袋子

题目描述

一个袋子里面有n个球,每个球上面都有一个号码(拥有相同号码的球是无区别的)。如果一个袋子是幸运的当且仅当所有球的号码的和大于所有球的号码的积。
例如:如果袋子里面的球的号码是{1, 1, 2, 3},这个袋子就是幸运的,因为1 + 1 + 2 + 3 > 1 * 1 * 2 * 3
你可以适当从袋子里移除一些球(可以移除0个,但是别移除完),要使移除后的袋子是幸运的。现在让你编程计算一下你可以获得的多少种不同的幸运的袋子。

输入描述:

第一行输入一个正整数n(n ≤ 1000)
第二行为n个数正整数xi(xi ≤ 1000)

输出描述:

输出可以产生的幸运的袋子数

示例1

输入

3
1 1 1

输出

2

思路:好像并没有太好的方法,深度优先搜索加上适当的剪枝做出的这道题目。。。还有一点就是避免重复。
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int res = 0;//全局变量返回值
void dfs(int sum, int mult, int index, bool flag, vector<int> & num){//flag是用来标记与前一个数字重复时前一个数字是否被计入。若前一个被计入则当前节点可计入,也可不计入;若前一节点未被计入则当前节点也不计入。(为了防止重复。)
    if(index == num.size()) return; //边界处理
    int newsum = sum+num[index];
    int newmult = mult*num[index];
    if(index == 0){  //第一个数的时候特殊处理,若最小的数不是1直接返回0
        if(num[0] == 1) {
            dfs(newsum, newmult,index+1,true,num);
            dfs(sum, mult,index+1,false,num);
        }else{
            return ;
        }
    }else{
        if(num[index] == num[index-1]){//与前一节点重复
            if(flag){//true的时候当前节点分两种讨论
                if(newsum>newmult) {//当前节点加入是否符合要求,若符合则继续,否则直接退出(剪枝)
                    res+=1;
                    dfs(newsum, newmult,index+1,true,num);
                }
                dfs(sum, mult,index+1,false,num);
            }else{//重复且前一节点未计入,则当前也不计入
                dfs(sum, mult,index+1,false,num);
            }
        }else{
            if(newsum>newmult) {
                res+=1;
                dfs(newsum, newmult,index+1,true,num);
            }
            dfs(sum, mult,index+1,false,num);
        }
    }
}

int main(){
    int counts = 0,temp;
    vector<int> nums;
    cin>>counts;
    for(int i=0;i<counts;++i){
        cin>>temp;
        nums.push_back(temp);
    }
    sort(nums.begin(),nums.end());//排序有利于后续剪枝
    dfs(0,1,0,false,nums);
    cout<<res;
    return 0;
}

看了一下网上其他同学的答案,总体思路还是相似的,但他们的好像更简洁一点。。。这里贴上其中一位的代码:

对重复元素的排除方法不一样。

#include <iostream>
#include <stdlib.h>
using namespace std;

int n;
int nums[1000];

int cmp(const void * a, const void * b) {
    return *(int*)a - *(int*)b;
}

// 思路:DFS生成全组合,同时注意剪枝、避免重复组合
int findall(int nums[], int index, long sum, long multi) {
    int count = 0;
    for(int i=index; i<n; i++) {
        sum += nums[i];
        multi *= nums[i];
        if(sum > multi)
            count += 1 + findall(nums, i+1, sum, multi);
        else if(nums[i] == 1)
            count += findall(nums, i+1, sum, multi);
        else
            break;
        sum -= nums[i];
        multi /= nums[i];
        // 跳过相等的元素,避免重复组合
        while(i<n-1 && nums[i]==nums[i+1])
            i++;
    }
    return count;
}

int main(int argc, char* argv[])
{
    while(cin >> n) {
        for(int i=0; i<n; i++)
            cin >> nums[i];

        // 从小到大排序
        qsort(nums, n, sizeof(int), cmp);
        cout << findall(nums, 0, 0, 1) << endl;
    }

    return 0;
}

原文地址:https://www.cnblogs.com/J1ac/p/9446011.html

时间: 2024-08-29 01:31:10

2017校招真题在线编程-幸运的袋子的相关文章

2019校招真题在线编程-牛牛找工作

时间限制:2秒 空间限制:65536K 热度指数:77851 本题知识点: 网易 Java工程师 C++工程师 iOS工程师 安卓工程师 运维工程师 前端工程师 算法工程师 PHP工程师 测试工程师 排序 模拟 贪心 题目描述 为了找到自己满意的工作,牛牛收集了每种工作的难度和报酬.牛牛选工作的标准是在难度不超过自身能力值的情况下,牛牛选择报酬最高的工作.在牛牛选定了自己的工作后,牛牛的小伙伴们来找牛牛帮忙选工作,牛牛依然使用自己的标准来帮助小伙伴们.牛牛的小伙伴太多了,于是他只好把这个任务交给

2016年上半年软考真题在线模拟测试,提前知晓你的成绩

2016年上半年软考于5月21日结束了,考试完想知道结果的急切心理,几乎每个经历过上学时代的人都能深刻体验到.如果你想知道你考的怎么样,如果你想要提前知道你的成绩,如果你想知道你哪个地方出错了,如果你想知道你哪个地方知识掌握的不够想要更深入的去理解,那就来希赛软考学院吧!希赛软考学院提供2016年上半年软考真题在线模拟测试,有标准的参考答案,有专业老师的解析视频,让你提前知晓你的成绩,让你再次巩固学习. 希赛授课专家介绍 张友生,计算机应用技术博士,软考培训教程系列丛书主编,考试指定教材<系统分

阿里巴巴2016数据挖掘工程师真题在线测

1.想要了解上海市小学生的身高,需要抽取500个样本,这项调查中的样本是? A.从中抽取的500名学生的身高 B.上海市全部小学生的身高 C.从中抽取的500名小学生 D.上海市全部小学生 2.以下对k-means聚类算法解释正确的是 A.能自动识别类的个数,随即挑选初始点为中心点计算 B.能自动识别类的个数,不是随即挑选初始点为中心点计算 C.不能自动识别类的个数,随即挑选初始点为中心点计算 D.不能自动识别类的个数,不是随即挑选初始点为中心点计算 3.以下哪个是常见的时间序列算法模型 A.R

2016校招真题编程-懂二进制

题目描述 世界上有10种人,一种懂二进制,一种不懂.那么你知道两个int32整数m和n的二进制表达,有多少个位(bit)不同么? 输入例子: 1999 2299 输出例子: 7 解题思路:异或,除二取余 源代码: package SuperHakceMainPackage; import java.util.Scanner; public class SuperHakceMian { int countBitDiff(int n,int m){ return n ^ m; } int findN

2018 拼多多 校招真题 最大乘积

最大乘积 时间限制:1秒 空间限制:32768K 热度指数:8197 校招时部分企业笔试将禁止编程题跳出页面,为提前适应,练习时请使用在线自测,而非本地IDE. 题目描述 给定一个无序数组,包含正数.负数和0,要求从中找出3个数的乘积,使得乘积最大,要求时间复杂度:O(n),空间复杂度:O(1) 输入描述: 无序整数数组A[n] 输出描述: 满足条件的最大乘积 示例1 输入 3 4 1 2 输出 8 思路分析:看到这个题目,下意识想到用Arrays.sort()排一下序, 因为输入的整数可以是负

2016校招真题之小球的距离

1.题目描述 小东和三个朋友一起在楼上抛小球,他们站在楼房的不同层,假设小东站的楼层距离地面N米,球从他手里自由落下,每次落地后反跳回上次下落高度的一半,并以此类推知道全部落到地面不跳,求4个小球一共经过了多少米?(数字都为整数) 给定四个整数A,B,C,D,请返回所求结果. 测试样例: 100,90,80,70 返回:1020 2.代码实现 1 package com.wcy.october; 2 3 /** 4 * 时间:2016年10月16日 题目:小球的距离 5 * 题目描述:小东和三个

校招真题练习014 万万没想到之聪明的编辑(头条)

万万没想到之聪明的编辑 题目描述我叫王大锤,是一家出版社的编辑.我发现一个发现拼写错误的捷径: 1. 三个同样的字母连在一起,一定是拼写错误,去掉一个的就好啦:比如 helllo -> hello2. 两对一样的字母(AABB型)连在一起,一定是拼写错误,去掉第二对的一个字母就好啦:比如 helloo -> hello3. 上面的规则优先“从左到右”匹配,即如果是AABBCC,虽然AABB和BBCC都是错误拼写,应该优先考虑修复AABB,结果为AABCC 请听题:请实现大锤的自动校对程序 输入

校招真题练习019 毕业旅行问题(头条)

毕业旅行问题 题目描述小明目前在做一份毕业旅行的规划.打算从北京出发,分别去若干个城市,然后再回到北京,每个城市之间均乘坐高铁,且每个城市只去一次.由于经费有限,希望能够通过合理的路线安排尽可能的省一些路上的花销.给定一组城市和每对城市之间的火车票的价钱,找到每个城市只访问一次并返回起点的最小车费花销. 输入描述:城市个数n(1<n≤20,包括北京)城市间的车票价钱 n行n列的矩阵 m[n][n] 输出描述:最小车费花销 s 牛客网上对此题的python语言判断似乎有问题,一直超时,之前做剑指O

精灵鼠从入口到出口最少减少速度(2019年哔哩哔哩校招真题)题解

题目以及输入输出描述: 题目很短.意思也很容易读懂. 题目要求就是  有一只老鼠,进入了一个迷宫,迷宫地图的大小为n*n.老鼠要从(起点)(0,0)坐标位置 到达 终点 (n-1,n-1)的位置. 老鼠的行动方式只有两种 —— 向下和向前. 每一个点都会让老鼠的速度降低(减少).求老鼠到达终点的时候最少减少的速度. 解题思路: 我们先考虑最后一步 到达终点,这一步可以从哪里来呢?根据题目分析因为老鼠只可以向下或者向前.所以到达终点(n-1,n-1)前,老鼠不是在(n-1,n-2), 就是在(n-