码迷,mamicode.com
首页 > 编程语言 > 详细

基于实验六对基于时间抽取随机不同数的算法研究

时间:2019-06-11 22:25:54      阅读:155      评论:0      收藏:0      [点我收藏+]

标签:是否有效   div   ++   随机数   直接   复数   linux系统   inux   相同   

实验报告链接:

https://www.cnblogs.com/nnn13579/p/10992122.html

 

对于基于时间抽取不同数,容易出现:

技术图片

 

这是某位同学的实验结果。

当中使用了这样的语句:

srand((unsigned)time(NULL));

和下面这条是一个效果:

srand((int)time(0));

问题就出在这里。

原因很简单,计算机运算速度很快,精确到秒对于计算机来说太大了。

那么将int改成double是否有效解决呢?

No,除非你用的是Linux系统的php,精确到毫秒。

而且当要抽的量大时,也可能重复。

所以我的第一想法是,当重复时,直接全部重抽好了。

所以有了如下代码:

 1     int k=0;
 2     do{
 3         srand((int)time(0));
 4         for(int i=0;i<n;i++)
 5             luck[i]=rand()%num;
 6         for(int i=0;i<n;i++)
 7             for(int j=i+1;j<n;j++)
 8                 if(luck[i]==luck[j]){
 9                     k=1;break;
10                 }
11     }while(k);

 

通过检测是否有抽出了相同数来确定是否重抽。

但显然,这种做法效率低下。

于是考虑在抽出相同数时,反复更改抽出的数来确保没有相同数。

于是:

 1 for(int i=0;i<n;i++){
 2     srand((double)time(0));
 3     luck[i]=rand()%num;
 4     int j=0,k=0;
 5     for(;j<i;j++)
 6         if(luck[i]==luck[j]){
 7             k=1;
 8             while(k){
 9                 srand((double)time(0));
10                 luck[i]=rand()%num;
11                 if(luck[i]!=luck[j]) {
12                     int t=0;
13                     for(;t<i;t++)
14                         if(luck[t]==luck[i]) break;
15                     if(t==i) k=0;
16                 }
17             }
18         }
19 }

 

但是,当抽40人时,起码要40+s,

效率低下的问题依旧没有解决。

那么优化算法,利用C(n)(m)=C(m-n)(m),增添以下内容:

 1  if(n<=num/2||n<=num/2+1){
 2         fun1(luck,n,date,num);
 3         fun2(luck,n);
 4     }
 5     else{
 6         int tluck[num-n];
 7         fun1(tluck,num-n,date,num);
 8         fun2(tluck,num-n);
 9         int tluckn=0,luckn=0;
10         for(int i=0;i<n;i++){
11             while(luckn==tluck[tluckn])
12                 luckn++;
13             luck[i]=luckn;
14             luckn++;
15         }
16     }

 

fun1()为抽取随机数的函数,fun2()为排序抽取的数。

但这治标不治本。

问题在哪里呢?

出在会抽出重复数。

对于抽n个数,极大可能抽了不止n次。

于是我有了一个想法,把抽过的数全部排除掉,然后在剩下数中抽取。

 1 void fun1(int luck[],int n,int num,int i,int all[]){
 2     if(i<n){
 3         srand((double)time(0));
 4         int t=rand()%num;
 5         luck[i]=all[t];
 6         for(int j=t;j<num-1;j++)
 7             all[j]=all[j+1];
 8         fun1(luck,n,num-1,i+1,all);
 9     }
10 }
11 ……
12 ……
13 ……
14 int all[num];
15 for(int i=0;i<num;i++)
16     all[i]=i;
17 fun1(luck,n,num,0,all);

 

all[]用于存储所有人的序号,

每个人的序号都有两种,

一种是在班里的序号,

另一种是在数组中的“房间号”。

而我们每次抽的都是房间号。

每次抽一个人后,将这个人踢掉,然后剩下的人一次向前移一个“房间”填补空位,实现房间里的人更新。

之后再用抽剩的人去抽下一轮。

由于

int t=rand()%num;

中,num值一直在变,随机的数也会一直变化,实现刷新。

即便一直抽取同一个“房间”,例如1号房,

但由于房间里的人已经换过了,所以不会是抽出同一人。

经过这次算法优化,能够实现抽n人只需要抽n次,抽取40人的时间压缩到了1s内。

基于实验六对基于时间抽取随机不同数的算法研究

标签:是否有效   div   ++   随机数   直接   复数   linux系统   inux   相同   

原文地址:https://www.cnblogs.com/nnn13579/p/11006246.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!