【问题标题】:How to implement a draw prize system where the prize has relative ratio of chance to obtain?奖品有相对获得率的抽奖制度如何实施?
【发布时间】:2015-04-30 06:40:04
【问题描述】:

例如,我有一个奖品列表,对于每个奖品,有一个相对比率常数,表示获得它的机会,如下面的代码所示:

vector<pair<string,int> > prizeBox;
prizeBox.push_back(make_pair("toy car",100));
prizeBox.push_back(make_pair("football",50));
prizeBox.push_back(make_pair("book",50));
prizeBox.push_back(make_pair("cash 1000",10));
prizeBox.push_back(make_pair("cash 5000",5));
prizeBox.push_back(make_pair("free expensive lunch",2));
prizeBox.push_back(make_pair("free expensive dinner",2));
prizeBox.push_back(make_pair("special big price",1));

在上面的代码中,“玩具车”有 100/(100+50+50+10+5+2+2+1) 的几率获得。我知道 rand() 可以用来获取随机数,但是在这种情况下我该如何使用它呢?

(另外我不相信我需要一个添加 100 个“玩具车”、50 个“足球”等的新向量来做到这一点......)

【问题讨论】:

    标签: c++


    【解决方案1】:

    您可以轻松地使用std::discrete_distribution,而不是创建自己的发行版:

    int main()
    {
        //create vector and fill it
        std::vector<std::tuple<std::string,int> > prizeBox { {"toy car",100}, {"football",50}, {"book",50}, {"cash 1000",10} };
    
        //create a vector of the second entries of vector-elements of prizeBox
        std::vector<int> chance;
        std::transform(std::begin(prizeBox), std::end(prizeBox), std::back_inserter(chance), [](auto p){return std::get<1>(p);});
    
        //set up the distribution and the random number generator
        auto dist = std::discrete_distribution<int>(std::begin(chance), std::end(chance));
        std::mt19937_64 rng;
    
        //draws ten time from the prize box
        for(int i=0;i<10;++i)
        {
            std::cout<<std::get<0>(prizeBox[dist(rng)])<<std::endl;
        }
    }
    

    DEMO

    编辑:上述解决方案的唯一问题是将元组的第一个条目复制到新向量中。 Here 您可以找到直接处理元组向量的方法。

    【讨论】:

      【解决方案2】:

      如果你想用加权概率索引,我想我会这样

      srand(time(NULL));
      
      vector<pair<string,int> > prizeBox; 
      
      int total = 100+50+50+10+5+2+2+1;
      
      int random = rand()%(total);
      if(random < 100){
          // acces to prizeBox[0];
      }
      else if(random < 150){
          //acces to prizeBox[1];
      }
      else if (random < 200)
          // and so on 
      

      PS : 你可以使用初始化列表来初始化你的标签(它比几个 push_back 更漂亮

          vector<pair<string,int> > prizeBox  = { {"toy car",100} , {"football",50} };
      

      【讨论】:

        【解决方案3】:

        这是一个根据您想要的机会随机抽取奖品的功能。这个想法是首先遍历向量并获得机会的总和。然后,生成一个从 1 到该总和的随机数并再次迭代,从随机数中减去当前机会。当随机数小于当前机会时,您将获得已排序的奖品。下面的代码显示了实现。

        #include <vector>
        #include <string>
        #include <stdlib.h>
        #include <time.h>
        
        using namespace std;
        
        string drawPrize (vector<pair<string, int> > prizeBox) {
            //iterate through vector to get the sum of the weigths.
            int total = 0;
            for (vector<pair<string,int> >::iterator it = prizeBox.begin() ; it != prizeBox.end(); ++it)
                total += it->second;
        
            // getting a random number
            srand(time(NULL));
            int r = rand() % total + 1; // a number from 1 to total
        
            // finding the prize
            vector<pair<string,int> >::iterator it = prizeBox.begin();
            while (r > it->second && it != prizeBox.end()) {
                r -= it->second;
                it++;
            }
        
            // returning the sorted prize
            return it->first;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-03-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-21
          • 2016-05-29
          • 1970-01-01
          相关资源
          最近更新 更多