编程题—随机发放奖品

内容会持续更新,有错误的地方欢迎指正,谢谢!

题目

在一次活动中,我们需要按可控的比例来随机发放我们的奖品,假设需要随机的物品id和概率都在给定的Map<String,Double> prizeMap中,请实现如下这个函数: String getRandomPrize(Map<String,Double>prizeMap){}使得返回的结果为参与者即将得到的一个随机物品id.
prizeMap中的数据为:
物品id 投放概率
1 0.5
2 0.3
3 0.1
4 0.95
5 0.05

分析

法1:直接从左到右一次相加。每次相加都记录相加后的结果:0.5 0.8 0.9 1.85 1.9,if(产生的随机数<=0.5)则说明选到了物品1,else if(产生的随机数<=0.8)则说明选到了物品2,以此类推。
法2:将0.5 0.3 0.1 0.95 0.05按照比例映射为[0,1]之间的数,再将映射后的五个数从左到右相加。剩余步骤同法1后半部分。

我用的法1

所用数据结构: map和string

代码

#include <iostream>
#include <string>
#include <map>//map由红黑树实现,其中的关键字有序
using namespace std;

string getRandomPrize(map<string,double> prizeMap)
{
    double sum=0;
    map<string,double>::iterator iter=prizeMap.begin();
    map<string,double> tempMap;
    while(iter!=prizeMap.end())
    {
        sum+=iter->second;
        tempMap.insert(pair<string, double>(iter->first,sum));
        ++iter;
    }

    //计时器原理实现种子,若每次调用时都重新设置种子了,那么多次调用的结果都是相同的
    //srand((unsigned)time(NULL));
    //产生[a,b]上的随机数 ((double)rand()/RAND_MAX)*(b-a) + a ,其中
    //(double)rand()/RAND_MAX)可以得到一个0~1的随机数
    double total = (double(rand()) / RAND_MAX) * sum;//产生0到sum之间的浮点数

    map<string,double>::iterator it=tempMap.begin();
    while(it!=tempMap.end())
    {
        if(total<(*it).second)
            return (*it).first;
        ++it;
    }
}

int main()
{
    map<string,double> prizeMap = {{"1",0.5},{"2",0.3},{"3",0.1},{"4",0.95},{"5",0.05}};
    int i=5000;
    srand((unsigned)time(NULL));//应该在这里设种子,这样每次调用结果才随机。
    while(i--)
        cout << getRandomPrize(prizeMap) << endl;
    return 0;
}

验证正确性:把main()改成如下代码:

//添加了统计每个id出现的次数的功能
int main()
{
    map<string,double> prizeMap = {{"1",0.5},{"2",0.3},{"3",0.1},{"4",0.95},{"5",0.05}};
    int i=5000;
    srand((unsigned)time(NULL));//应该在这里设种子,这样每次调用结果才随机。
    string temp;
    int count[6]={0};
    while(i--)
    {
        temp=getRandomPrize(prizeMap);
        cout<<temp<<endl;
        count[atoi(temp.c_str())]++;
    }
    for(int i=1;i<=5;++i)
        cout<<count[i]<<" : ";
    return 0;
}

输出结果为:

1243 : 790 : 267 : 2567 : 133 约等于 0.5:0.3:0.1:0.95:0.05

结论:正确!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值