(算法)随机播放歌曲

题目:

假设张三的mp3里有1000首歌,现在希望设计一种随机算法来随机播放。与普通随机模式不同的是,张三希望每首歌被随机抽到的概率是与一首歌的豆瓣评分(0~10分)成正比的,如朴树的《平凡之路》评分为8.9分,逃跑计划的《夜空中最亮的星》评分为9.5分,则希望听《平凡之路》的概率与《夜空中最亮的星》的概率比为89:95,。现在我们已知这1000首歌的豆瓣评分:
    (1)请设计一种随机算法来满足张三的需求。
    (2)请写代码实现自己的算法。

思路:

将1000首歌的豆瓣评分累加起来,成为一条1000个区间的数轴,每个区间代表一首歌曲,在每个区间内是均匀分布的,而区间与区间之间满足概率与豆瓣评分成正比。

这样,通过产生一个[0,totalScore]间的随机浮点数,落在哪个区间就播放哪首歌曲。

代码:

#include <iostream>
#include <time.h>
#include <stdlib.h>

using namespace std;

int findIdx(double songs[],int n,double rnd){
    int left=0;
    int right=n-1;
    int mid;
    while(left<=right){
        mid=(left+right)/2;
        if((songs[mid-1]<=rnd) && (songs[mid]>=rnd))
            return mid;
        if(songs[mid]>rnd)
            right=mid-1;
        else
            left=mid+1;
    }
//    return mid;
}

int randomPlaySong(double sum_scores[],int n){
    double mx=sum_scores[n-1];
    double rnd= rand()*mx/(double)(RAND_MAX);
    return findIdx(sum_scores,n,rnd);
}

int main()
{
    srand(time(0));
    double scores[]={5.5,6.5,4.5,8.5,9.5,7.5,3.5,5.0,8.0,2.0};
    int n=sizeof(scores)/sizeof(scores[0]);
    double sum_scores[n];
    sum_scores[0]=scores[0];

    for(int i=1;i<n;i++)
        sum_scores[i]=sum_scores[i-1]+scores[i];

    cout<<"Calculate the probability of each song: "<<endl;
    int totalScore=sum_scores[n-1];
    for(int i=0;i<n;i++)
        cout<<scores[i]/totalScore<<" ";
    cout<<endl;

    int counts[n];
    for(int i=0;i<n;i++)
        counts[i]=0;

    int i=0;
    int idx;
    int MAX_ITER=100000000;
    while(i<MAX_ITER){
        idx=randomPlaySong(sum_scores,n);
        counts[idx]++;
        i++;
    }

    cout<<"After simulation, probability of each song: "<<endl;
    for(int i=0;i<n;i++)
        cout<<1.0*counts[i]/MAX_ITER<<" ";
    cout<<endl;

    return 0;
}

运行结果:

基于豆瓣评分的每首歌曲的概率以及一亿次的随机试验结果,可以看出基本一致:

原文地址:https://www.cnblogs.com/AndyJee/p/4463646.html