实验报告链接:
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,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,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,num,0,all);
all[]用于存储所有人的序号,
每个人的序号都有两种,
一种是在班里的序号,
另一种是在数组中的“房间号”。
而我们每次抽的都是房间号。
每次抽一个人后,将这个人踢掉,然后剩下的人一次向前移一个“房间”填补空位,实现房间里的人更新。
之后再用抽剩的人去抽下一轮。
由于
int t=rand()%num;
中,num值一直在变,随机的数也会一直变化,实现刷新。
即便一直抽取同一个“房间”,例如1号房,
但由于房间里的人已经换过了,所以不会是抽出同一人。
经过这次算法优化,能够实现抽n人只需要抽n次,抽取40人的时间压缩到了1s内。
总结以上是内存溢出为你收集整理的基于实验六对基于时间抽取随机不同数的算法研究全部内容,希望文章能够帮你解决基于实验六对基于时间抽取随机不同数的算法研究所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)