(算法)随机播放歌曲

题目:

假设张三的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;

}

运行结果:

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

 

(算法)随机播放歌曲

你可能感兴趣的:(算法)