题目:
假设张三的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; }
运行结果:
基于豆瓣评分的每首歌曲的概率以及一亿次的随机试验结果,可以看出基本一致:
时间: 2024-12-12 10:46:18