这个算法如何实现?(35分)

  • 主题发起人 kidman520
  • 开始时间
K

kidman520

Unregistered / Unconfirmed
GUEST, unregistred user!
一个需要随机取数据的算法:
例如:我有三个班的学生,每个班30人,学号是统一的标示,现在我把这三个班的学生放
在一起,然后从中间随机的选取30个人,放在一个教室,在随机的取出30人,放在第二个
教室,最后的30个人放在第三个教室。如何实现从整个的数据集中一次随机的取出多个数
据,这个算法改如何实现,希望大家指教,多谢了!!!
 
random函数[:D]
 
var lab :array[1..90] of boolean;i,cnt:integer;
a,b,c:array[1..30] of integer;//重组后的3个教室
for i:=1 to 90do
lab:=false;//初始标记
cnt:=1;
repeat //选取第一个教室学生号
a[cnt]:=random(90);
while lab[a[cnt]]do
a[cnt]:=random(90);//略过已做的标记的学生
lab[a[cnt]:=true;
//做标记
cnt:=cnt+1;
until cnt>30
cnt:=1;
repeat
while lab[b[cnt]]do
b[cnt]:=random(90);
lab[b[cnt]:=true;
cnt:=cnt+1;
until cnt>30
cnt:=1;
for i:=1 to 90do

if not lab then

begin
c[cnt]:=i;cnt:=cnt+1 end;
//剩下没有标记的都是c教室了

 
我的思路:
设一个动态数组,开始长度为90,记录这90个学生的号码,
然后产生30个随机数,范围为1~90,然后用这些随机数作为
数组下标取出30个,原来的数组减去这30个剩下60个;再
随机产生30个随机数,范围1~60,同上一步。剩下的就只有
30个,不用再取了。
编程实现很简单,照楼上的做法就是了。不过取随机数的范围
一定要注意:第一次是random(90),第二次是random(60).
 
提示!random为伪随即函数,每次运行程序他都是按照原先的顺序“随机”抽取整数,
如果你是用于考试的话,第一次还可以,下一次排出来的还是这个顺序,下一次还是。。。
所以你最好再增加几个随机种子,比如时间,硬件参数等等,按照这个种子数循环取n遍
random值
 
对应每个学生给个随机数,然后根据所给的随机数对学生排序。随机数的范围大一些
前30,中间30,后30分班即可。
 
你们所说的这种方法我想过了,如果我有90个学生,我要取90次,如果我有1000个,岂非
要取1000次,我想问问大家有没有能够一次随机取出30个学生呢?这才是我问的重点,刚
才没有说清楚,不好意思!!!
 
to bluenats,
random为伪随即函数,每次运行程序他都是按照原先的顺序“随机”抽取整数,
如果你是用于考试的话,第一次还可以,下一次排出来的还是这个顺序,下一次还是。。。
其实我们在调用random之前可以调用随机化函数啊
randomize;
这样不就可以实现每次都不一样了
to kidman520:
你干脆就把随机化做成一个过程嘛。管它那个过程取100次,1000次。反正我
要用就调用它好了
 
我看jsxjd的方法不错,你可以只用算一次就可以了,
 
参照洗牌的算法:
在90个数组元素中随机抽取两个互换位置,重复进行n次,然后前30在一班,
中30在2班,后30在3班。适当调整n值可以取得很好的效果。
 
random函数是伪随机不可
用Randomize
 
rjiajia的方法不能保证,号码不重复,需要设置一个集合,每次判断Random产生的数是否在里面,在里面如何不在里面又如何,必须判断
 
"不是普通的笨" 的方法还不错!
 
事实上是一个组合的问题
90取30
 
学习学习!
 
如果要输出结果遍历一次数据集是不可避免的。我的思路是在输出每个学生的数据
时产生一个0..2的随即数,用于表示该学生被分到哪个教室,同时用一个三个分量
数组记录某教室的人数,满30人后就不要再分配。这样只需在打印输出的时候决定
应分配在哪个教室,与打印时的遍历(不可避免的)同时进行。我想这样效率最好
 
至于要做到那么随机么???不就是分个班么...
 
用链表不就行了,随机取出一个,断开,再随机取不就了。
 
用数组Tuatara方法最好
用链表当然DDK的方法最好
 
多人接受答案了。
 
顶部