2017校招真題在線編程-幸運的袋子
阿新 • • 發佈:2018-08-09
emp push_back main urn sum ews bject ret tor
例如:如果袋子裏面的球的號碼是{1, 1, 2, 3},這個袋子就是幸運的,因為1 + 1 + 2 + 3 > 1 * 1 * 2 * 3
你可以適當從袋子裏移除一些球(可以移除0個,但是別移除完),要使移除後的袋子是幸運的。現在讓你編程計算一下你可以獲得的多少種不同的幸運的袋子。
題目描述
一個袋子裏面有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; }
2017校招真題在線編程-幸運的袋子