阿里笔试 4.29 第一题分水果
/*
题目:n种口味的水果分给m个人,每个人只能选一种水果,每种水果可以分给多个人,每个人分得的水果数相等,
问每个人最多可以得到多少水果?
#阿里笔试2020##笔试题目##阿里巴巴#
题目:n种口味的水果分给m个人,每个人只能选一种水果,每种水果可以分给多个人,每个人分得的水果数相等,
问每个人最多可以得到多少水果?
*/
思路:由题意可知,每个人只能选择一种水果,因此我们需要让每个人从 n 种水果中随机选择一种苹果,每个人可以重复选择一种水果,
设置一个数组man[m],man[i] 保存第 i 个人所选择的种类;每个人选择的种类好种类后,就将水果按照每个人的选择逐个的循环发放给每个人,为了确保
每个人分的水果相等,当某种水果发放完毕时停止,此时,该种水果原有的数量除以所选择该种水果的人数(不够除就取整),即为每个人的最大水果数。
每个人选择水果的种类的不同都可能会造成最后的结果不同,因此问题的关键就是找到每一种可能的水果种类选择方式,即求出每一种 man[n] ,我这里
采用 暴力搜索+回溯 的方式寻找,当每找到一种选择情况后就求出该种情况下每个人能得到的水果数,保存每一种情况下的最大值即为所求,这里用 max 来保存;
注:这里暴力搜索其实是一种树形结构的深度优先遍历,树形结构为 n 叉树,每一个子树表示每个人选择的水果种类,数的层数为 m ,即人数,第 k 层表示第 k 个
人在第 k - 1个人已经选择的情况下继续选择 n 种水果之一,直达每个人都选择完毕(k > = m,k从0开始)为止。
暴力搜索的方式比较费时,可以适当的加一些剪枝条件来加速。
我觉得我这种办法有些笨,如果有大佬有比较简便的方法求多多指教啊!
#include<iostream> #include<vector> #include<algorithm> using namespace std; int max_Find(vector<int> apple, vector<int> man){ int count = 0; //开始发水果 while(1){ for(int i = 0; i < man.size(); i++){ //每个人按照选择的种类发放一个水果 if(apple[man[i]] == 0){ //某种水果分配完毕,结束分配 return count; } else{ apple[man[i]]--; } } count++; //每分配一次每个人得到的水果个数加一 } } void dfs_Choice(vector<int> &apple, vector<int> &man, int k, int &max){ if(k >= man.size()){ //每个人都选择完毕 int tmp = max_Find(apple, man) + 1; //分配剩下的水果并求得当前选择下的每人的最大水果数,此前每人已经分配了一个水果 max = tmp > max ? tmp : max; return; } //第 k 个人选择水果种类 for(int i = 0; i < apple.size(); i++){ if(apple[i] == 0){ //该种水果已经没有了,选择下一种 continue; } man[k] = i;//第n个人选第 i 种水果 apple[i]--; dfs_Choice(apple, man, k+1, max); //第k+1个人选择水果种类并得到一个该类水果 apple[i]++; //回溯 man[k] = -1; } } int main(){ int T = 1; cin >> T; //循环次数 int n,m; //n种水果分给m个人 int count = 0; vector<int> apple; //存放每一种水果的个数 vector<int> man; //存放每个人选择的水果种类 while(count < T){ cin >> n >> m; int total = 0; apple.assign(n,0); man.assign(m,-1); for(int i = 0; i < n; i++){ cin >> apple[i]; total += apple[i]; } if(total < m) { //水果不够分,输出0 cout << 0 << endl; continue; } int max = 0; //保存每个人能分配的最大水果数 dfs_Choice(apple, man, 0, max); //从第 0 个人开始选择水果种类 cout << max << endl; count++; } return 0; }
#阿里笔试2020##笔试题目##阿里巴巴#