2017校招真题在线编程-幸运的袋子
Posted j1ac
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017校招真题在线编程-幸运的袋子相关的知识,希望对你有一定的参考价值。
题目描述
一个袋子里面有n个球,每个球上面都有一个号码(拥有相同号码的球是无区别的)。如果一个袋子是幸运的当且仅当所有球的号码的和大于所有球的号码的积。
例如:如果袋子里面的球的号码是{1, 1, 2, 3},这个袋子就是幸运的,因为1 + 1 + 2 + 3 > 1 * 1 * 2 * 3
你可以适当从袋子里移除一些球(可以移除0个,但是别移除完),要使移除后的袋子是幸运的。现在让你编程计算一下你可以获得的多少种不同的幸运的袋子。
例如:如果袋子里面的球的号码是{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; }
以上是关于2017校招真题在线编程-幸运的袋子的主要内容,如果未能解决你的问题,请参考以下文章