【求一高效算法,感兴趣的朋友可以来试试,高分】解决方案整理系列三

讨论了在不同数量的礼物和小朋友的情况下如何公平分配礼物的问题。提出了多种解决方案,包括使用列表、随机数生成、位图法等,并对算法的性能进行了评估。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题: (帖子路径:http://topic.youkuaiyun.com/u/20091027/09/db4cd117-bfbe-491f-bcb8-d54ee08c0787.html
求一个高效算法:
有100名小朋友,
现在有一堆礼物
若是礼物数量小于100,比如为81,则这个81份礼物随机分配给小朋友,但要确保是一个人只能拿到一份礼物;

若是礼物数量大于100,
比如为115,则每个人至少有一份礼物,部分人有两份礼物,但没人拿到两份份以上的礼物;
比如为245,则每个人至少有两份礼物,部分人有三份礼物,但没人拿到三分份以上的礼物;

就是这个思路,这里声明不是大学老师布置的题目啊,是自己工作中一个抽象出来的问题,
希望得到大家的思路,,参与者,高分重谢!
也是个大家交流的机会


这个帖子让我感慨,我们csdn论坛中卧虎藏龙,真的很佩服,

本次系列一,把主要的解决思想整理一下

地址:http://blog.youkuaiyun.com/yinyuan1987/archive/2009/10/30/4748636.aspx

系列二,把大家使用不同的解决方法或实例提出来共享一下

地址:http://blog.youkuaiyun.com/yinyuan1987/archive/2009/10/30/4748671.aspx

系列三,把大家对性能方面思路提出来共享一下

地址:http://blog.youkuaiyun.com/yinyuan1987/archive/2009/10/30/4748715.aspx

三.对性能方面的思考:

79楼朋友asxinyu_usst说:

楼主说的是不是礼品和人数都很大时,产生的随机数会冲突导致效率降低啊?
我认为,上面的方法有几种都可行,关键是用的随机数和打乱小朋友的算法效率?

如果人数比较少呢,把小朋友打乱,相当于产生一个随机全排列,每次按照这个随机全排列来打乱,然后从头到尾分配即可;这种随机全排列的生产算法我研究过,我有比较好的方法实现。

如果人数比较多的话,产生随机全排列的方法不一定可行,但是呢,可以对问题进行分块,在块内进行随机分配,我想你抽象出来的问题既然要随机分配的话,应该对这个随机性有些要求,否则直接从头到尾分好了。

我认为 随机性的这个要求不同会影响到算法的效率。

78楼朋友引用71 gukuitian 的回复:
我比较倾向于用list,参与过的元素remove掉。 设人数a,礼物数b,且a>b;(a <b不用说了) 我不知道有什么好的打乱数组的方法。 1:从1到a循环,每次生成一个随机数,每个元素都交换一回, 2:每次两个随机数。两元素交换,循环n次,(最少也要a/2次吧) 极端点:a=10000,b=1; 用list只要生成一个随机数, 数组打乱要10000 或5000次。 通常点: 用list最多也就a/2次生随机数的操作, 数组打乱还是要10000 或5000次。 谁能提供个好点的洗牌法?

这个洗牌算法 就类似于生成一组全排列数据啊。。。我有过研究。。。如果你需要的随机性高,花的时间就多点。。。。

98楼朋友sbwwkmyd提供了:

位图法生成随机数

public static int[] subGifts100(int count) { int[] value = new int[100]; if (count > 0) { int avgValueLess = count / 100, avgValue = avgValueLess + 1, bits; ulong highBits = 0, lowBits = 0, andBits; bool isSub = (count %= 100) < 50; if (isSub) count = 100 - count; for (Random random = new Random(); count != 100; count++) { if ((bits = random.Next(count)) >= 64) highBits = ((highBits >> (bits -= 64)) << (bits + 1)) | (andBits = 1UL << bits) | (highBits & (andBits - 1)); else { highBits = (highBits << 1) | (lowBits >> 63); lowBits = (bits == 63 ? 0 : ((lowBits >> bits) << (bits + 1))) | (andBits = 1UL << bits) | (lowBits & (andBits - 1)); } } for (count = 0; count < 64; lowBits >>= 1, count++) value[count] = isSub ^ ((lowBits & 1) == 0) ? avgValue : avgValueLess; for (; count < 100; highBits >>= 1, count++) value[count] = isSub ^ ((highBits & 1) == 0) ? avgValue : avgValueLess; } return value; } public static int[] subGifts(int childrenCount, int count) { int[] value = null; if (childrenCount > 0 && count >= 0) { value = new int[childrenCount]; if (count > 0) { ulong bitValue, andBits; int nextBit, bits, avgValueLess = count / childrenCount, avgValue = avgValueLess + 1, bitSum = 0, endCount = childrenCount & 0x7fffffc0, t = 0; bool isSub = (count %= childrenCount) < (childrenCount >> 1); Random random = new Random(); if (isSub) count = childrenCount - count; long allCount = (long)count; for (count = 64; count <= endCount; count += 64) { nextBit = (int)((allCount * count) / childrenCount) - bitSum; bitSum += nextBit; for (bitValue = 0; nextBit != 64; nextBit++) bitValue = ((bits = random.Next(nextBit)) == 63 ? 0 : ((bitValue >> bits) << (bits + 1))) | (andBits = 1UL << bits) | (bitValue & (andBits - 1)); for (nextBit = count - 64; bitValue != 0; nextBit++, bitValue >>= 1) t += (value[nextBit] = isSub ^ ((bitValue & 1) == 0) ? avgValue : avgValueLess); while (nextBit != count) t += (value[nextBit++] = isSub ? avgValueLess : avgValue); } if ((endCount = childrenCount & 63) != 0) { nextBit = (int)allCount - bitSum; for (bitValue = 0; nextBit != endCount; nextBit++) bitValue = ((bits = random.Next(nextBit)) == 63 ? 0 : ((bitValue >> bits) << (bits + 1))) | (andBits = 1UL << bits) | (bitValue & (andBits - 1)); for (nextBit = count - 64; bitValue != 0; nextBit++, bitValue >>= 1) t += (value[nextBit] = isSub ^ ((bitValue & 1) == 0) ? avgValue : avgValueLess); while (nextBit != childrenCount) t += (value[nextBit++] = isSub ? avgValueLess : avgValue); } } } return value;

184楼朋友wo554006164测试:

/// <summary> /// 分配礼物 /// </summary> /// <param name="p_presentNumber">礼物数量</param> private void distribution(int p_presentNumber) { const int CHILDREN_NUMBER = 10000; int[] children = new int[CHILDREN_NUMBER];//100个小朋友 int[] shuffle = new int[CHILDREN_NUMBER];//随机编号,按着编号发礼物 Hashtable ht = new Hashtable(); int basePresentNum = p_presentNumber / CHILDREN_NUMBER;//小朋友最少要拿的礼物数量 int residualNum = p_presentNumber % CHILDREN_NUMBER;//多出的礼物数量 int i = 0; int rdnum = 1; //生成随机编号 while (i < CHILDREN_NUMBER) { Random random = new Random(rdnum++ * DateTime.Now.Millisecond); int rdResult = random.Next(CHILDREN_NUMBER); if (!ht.ContainsKey(rdResult)) { ht.Add(rdResult, rdResult); shuffle[i++] = rdResult; //Console.WriteLine("第"+i+"个编号:"+rdResult.ToString()); } } //按编号给小朋友发礼物,前residualNum个小朋友会多一个礼物 for (i = 0; i < CHILDREN_NUMBER; i++) { if (residualNum > i) children[shuffle[i]] = basePresentNum + 1; else children[shuffle[i]] = basePresentNum; } /*Console.WriteLine("小朋友分得的礼物数量:"); for (i = 0; i < CHILDREN_NUMBER; i++) { Console.WriteLine("第"+(i+1)+"个小朋友得到:"+children[i].ToString()+" 礼物"); } Console.WriteLine("按小朋友分到的礼物数量进行排序:"); for (i = 0; i < CHILDREN_NUMBER; i++) { for (int j = CHILDREN_NUMBER-1; j >i; j--) { if (children[j] > children[i]) { int temp = children[j]; children[j] = children[i]; children[i] = temp; } } } for (i = 0; i < CHILDREN_NUMBER; i++) { Console.WriteLine(children[i].ToString()); }*/ // Console.Read(); }

我写了个,礼物1亿,小朋友1万时用时在1秒左右.不怎么样!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值