糖果谜题
糖果谜题
http://www.nowcoder.com/questionTerminal/8ff3e3a14ea04c6bb3a60e2e457dafb1
题解:
题目难度:中等
知识点:数学逻辑、动态数组、map
首先要明确:当小朋友所报数字相同时,小朋友可互相认为对方和自己颜色相同;当小朋友所报数字不相同时,那么双方颜色一定不相同。
方法一:
步骤一:首先将小朋友所报数字放入动态数组v中,记录小朋友人数res初始化值为0。
步骤二:构造map依次对数组v中的数字进行判断,判断方法如下:
1.判断该数字v[i]作为键值是否已经存入map中,若没有存入,将其放入,并将m(v[i])值设置为1(该值表示到现在为止该数字v[i]出现的次数,由于此处为初次出现,所以将其值设置为1);小朋友人数res值加上v[i]+1。(v[i]表示有几个小朋友和自己相同,那么其值可以理解为拿到该颜色糖果的小朋友数目)。
2.如果该数字v[i]已经出现,判断m[v[i]]的值是否大于v[i]+1,如果值小于v[i]+1,那么让m[v[i]]的值加一即可。
3.如果m[v[i]]的值大于v[i]+1时(表明之后出现该数字的小朋友要重新组成一队,如:数字2一共出现5次,那么有两队),m[v[i]]重新设置为1,res的值加上v[i]+1。
步骤三:输出res
【注】:数字2一共出现5次,其例子运算过程如下表。通过该例子很容易理解有多种不同值输入的运算情况。其中需要注意:每当m[v[i]]的值设置为1时,小朋友数目res添加v[i]+1,而不是每当m[v[i]]的值等于v[i]+1时小朋友数目增加。因为最后一对可能不能达到v[i]+1,这是最后一对我们需要填满。(同该情况:只有一个小朋友报数为3,那么根据该信息至少存在4个小朋友)
#include<iostream> #include<vector> #include<map> using namespace std; int main() { vector<int> v; int t; //将输入放到Vector中 while(cin>>t) v.push_back(t); map<int,int> m; int res = 0; //遍历Vector的值 for(int i = 0;i<v.size();i++) { if(m.find(v[i]) == m.end()) { m[v[i]] = 1; res+=v[i]+1; } else if(m[v[i]]<=v[i]) { m[v[i]]++; } else { m[v[i]] = 1; res+=v[i]+1; } } cout<<res<<endl; return 0; }
方法二
上述方法一是对依次输入数据进行判断,方法二直接将输入保存在map中,每个键值(输入值加一)对应的值为该数出现的次数。如输入:1 1 3,那么m[2]=2,m[4]=1。可以简单理解为有两种抱团方式,一种是两个人抱团,一种是4个人抱团。现在可以两个人抱团的有2个人,4个人抱团的有一个人。那么,这两个人直接抱团,4个人抱团的现在只有一个人,那么肯定至少还需要3人组成一个4人团。
从上分析可得:遍历map,我们将键值赋值给变量J,所对应的值赋给k。那么可以理解为:抱团方式为J个人抱团,需要抱团的人数为k个。k/j表示可以直接抱多少个团,那么人数等于团数乘上每个团的人数,即(k/j)*j;如果不能整除,那么就会有人剩下没有加入组团,需要给他们添加人到一个团需要的数量j。
#include<iostream> #include<vector> #include<map> using namespace std; int main() { map<int,int> m; map<int,int>::iterator iter; int t; while(cin>>t) m[t+1]++; int count=0; for(iter=m.begin();iter!=m.end();iter++){ int j,k; j=iter->first; k=iter->second; if(k%j==0) count+=(k/j)*j; else count+=(k/j)*j + j; } cout<<count; return 0; }