Heim > Fragen und Antworten > Hauptteil
以前想过一个类似问题,就是没有每个人最大、最小的得钱数的限制,以前的问题可以很好用随机数解决。
于是这个问题也被以前的思想带坑里了,把突破口完全放在了如何处理每个人的随机数上。
于是在面试时间就没有解决这个问题,直到面试结束自己安静下来,仔细想想,发现思路错了。
我认为正确的思路是:每个人先得6块钱,这样剩下40块钱,之后每次拿出一块钱,随机分配给一个人,如果某个人的钱数达到了上限,那么这个人下次就没有了再得到钱的资格了。这样直到剩下钱都分配完。
当然在接口的实际处理上可以做些优化,例如剩下的钱每次随机分配的钱可以是随机的(当然这个随机要做一些限制,以免一下就分配超额了),然后如果某个人钱+这次随机分配的钱>每个人的上限,那么他就没有资格得到这个钱了。
随机分配也好实现,先算有几个人有资格得到这笔钱,随即一个数,决定给第几个符合资格
的人。
我的思路就是这样,大家如果有更好的思路,请告知。谢谢。
PHP中文网2017-04-11 09:56:50
一个do while循环就能解决的问题,搞那么复杂。
<?php
$money = 40;
$people = array_fill(0, 10, 6);
do {
$lucky_index = mt_rand(0, 9);
$lucky_money = floatval(substr(mt_rand() / mt_getrandmax(), 0, 4));
if($people[$lucky_index]+$lucky_money >= 12)
continue;
if($money < 1) {
$m = $money;
} else {
$m = $lucky_money;
}
$people[$lucky_index] += $m;
$money -= $m;
} while($money > 0);
print_r($people);
?>
高洛峰2017-04-11 09:56:50
你的想法基本靠谱,我认为可以这样分:
1.先每人分6元,还剩下40元。
2.起一个循环,每人分0-(12-他已有的钱)元随机,直到钱分完为止。
没有题主讲的这么麻烦的。
高洛峰2017-04-11 09:56:50
$arr = [];
for ($i=0; $i < 9; $i++) {
$arr[] = mt_rand(6,12);
}
array_push($arr, 100 - array_sum($arr));
var_dump($arr);
var_dump(array_sum($arr));
ringa_lee2017-04-11 09:56:50
先每个人分6分,然后把剩下的钱再分
这个时候取10个随机值(0-9)随意,然后取各个值在随机值总和的百分比,分别乘以剩下的10000-60;Math.ceil或者Math.floor都可以
最后一个值防止取ceil时溢出,直接用10000-60-前面九个数的和即可
然后分别加上6,换算即可
PHP中文网2017-04-11 09:56:50
<?php
// 1.初始化,平均分配每人$initAvgMoney(根据限制条件随机产生)
// 2.每人随机拿出一定金额到共享资金池中,进行重新分配
// 限制条件:$initAvgMoney应满足条件:"小宝"一分钱也不放入共享资金池("特自私"),其余九人拿出尽可能多的钱到共享资金池(每人只留6元)的情况下,共享资金池平均分配后小宝的钱也不超过12块
header("Content-type:text/html;charset=utf-8");
$minInitAvgMoney = 600;
// ($maxInitAvgMoney - 600) * 9 / 10 + $maxInitAvgMoney <= 1200;
$maxInitAvgMoney = floor(1740 / 1.9);
echo("maxInitAvgMoney:");var_dump($maxInitAvgMoney);
$initAvgMoney = mt_rand($minInitAvgMoney, $maxInitAvgMoney) ;
echo("initAvgMoney:");var_dump($initAvgMoney);
$maxMinus = $initAvgMoney - 600;
echo("maxMinus:");var_dump($maxMinus);
$moneyArr = array();
for($i = 0; $i < 10; $i ++){
$randMinusArr[$i] = mt_rand(0, $maxMinus / 10) * 10;
// echo("randMinusArr-{$i}");var_dump($randMinusArr[$i]);
$moneyArr[$i] = $initAvgMoney - $randMinusArr[$i];
}
$randMinusSum = 10000 - $initAvgMoney * 10 + array_sum($randMinusArr);
$avgAddMoney = $randMinusSum / 10;
for($i = 0; $i < 10; $i ++){
$moneyArr[$i] = ($moneyArr[$i] + $avgAddMoney) / 100;
}
echo "最终结果:";var_dump($moneyArr);
echo "结果验证:";var_dump(array_sum($moneyArr));
// 感觉还有可以完善的地方,先这样吧
阿神2017-04-11 09:56:50
min = 6;
max = 12;
total = 100;
pe = 10;
maxTotal = max*pe - total;
list = array();
for (0<pe)
if(maxTotal>0)
temp = random(0,maxTotal>=6?6:maxTotal);
maxTotal-=temp;
list.push(12-temp);
if(maxTotal>0)
pre = maxTotal/pe;
for (0<pe)list[temp2]+=pre;
shuffle(list);
此方法是错误的,没有强迫症,不修改了
PHP中文网2017-04-11 09:56:50
半夜看到这个问题,忽然想到二分法那种模式,于是搞了一个解决方案,先讲思路。
1.先将人分为两半,左半人分的总金额最少是左半人数x最少金额和总金额-右半人数x最多金额两个数字中较大的;
2.左半人分的总金额最多是左半人数x最多金额和总金额-右半人数x最少金额两个数字中较小的;
3.在这个范围内取随机数作为分给左半人的金额,然后将问题递归为左半人分钱和右半人分钱。
py代码(直接以分为单位,数字都是整数):
import random
def deliver(sum_of_money,num_of_people,min_of_money,max_of_money):
if num_of_people==1:
arr = [sum_of_money]
return arr
else:
half = num_of_people>>1
border_left = max(min_of_money*half,(sum_of_money-(num_of_people-half)*max_of_money))
border_right = min(max_of_money*half,(sum_of_money-(num_of_people-half)*min_of_money))
sum_of_left = random.randint(border_left,border_right)
arr_left = deliver(sum_of_left,half,min_of_money,max_of_money)
arr_right = deliver(sum_of_money-sum_of_left,num_of_people-half,min_of_money,max_of_money)
return arr_left+arr_right
list = deliver(10000,10,600,1200)
print list
阿神2017-04-11 09:56:50
根据题主的思路写了这样的一个答案
function faHongBao(money, pe, min, max) {
var sum = money,
result = [];
for(var i=0; i<pe; i++) {
result.push(min);
sum -= min;
}
while(sum > 0) {
var ran = Math.floor( Math.random() * (pe - 1) );
if(result[ran] < max) {
result[ran]++;
sum--;
}
}
return result;
}
怪我咯2017-04-11 09:56:50
static void Main(string[] args)
{
int all = 100;//总金额
int person = 10;//人数
double min = 8;//最小金额
double max = 12;//最大金额
double[] array = new double[person];//分配结果集
int i = 0;//第几人
Random ran = new Random();
//默认分配最小值
for (i = 0; i < person; i++)
{
array[i] = min;
}
double yet = min * person;//已分配金额
int whileTimes = 0;//记录循环次数
while (yet < all)
{
double thisM = Math.Round((ran.NextDouble() * (max - min - 1)), 2);
i = ran.Next(0, person);
if (yet + thisM > all)
{
thisM = all - yet;
}
if (array[i] + thisM < max)//判断是否超出最大金额
{
array[i] += thisM;
yet += thisM;
}
whileTimes++;
}
Console.Write("共循环{0}次\r\n", person + whileTimes);
yet = 0;
for (i = 0; i < person; i++)
{
yet += array[i];
Console.Write("第{0}人=>分配{1}元,合计分配{2}元\r\n", i + 1, array[i], yet);
}
Console.Read();
}
伊谢尔伦2017-04-11 09:56:50
function roundmoney()
{
$cash=100;
for ($i = 0; $i < 10; $i++) {
$people[$i]=rand(6,12);
$cash=$cash-$people[$i];
if($cash==0&&$i==9)
{
return $people;
}
}
return false;
}
while(true)
{
if(($res=roundmoney())!=false)
{
var_dump($res);
break;
}
}
感觉有点粗暴,就是完全让计算机随机分,什么时候刚好分够10个人并且每个人不少于6不大于10 就停止