;~ 分析。N个人,N>=2,N<=50 N=随即数(2,50,1)
;~ 人编号从1-N.即:MAN1,MAN2,MAN3,....,MANN
;~ 如果MAN1-->MAN2,MAN1-->MAN3, 则,MAN2--/>MAN1,MAN3--/>MAN1.
;~ 如果MAN1--/>MAN2,MAN1--/>MAN3,则,MAN2-->MAN1,MAN3-->MAN1 或 MAN2--/>MAN1,MAN3--/>MAN1
;~ MAN1~MANN--->MANMAX, MANMAX-->MANMAX
#include <array.au3>
Global $N=50 ;总人数
Global $XB[$N] ;数字列表,随机出一个之后自动从该数组中删除该元素.
Global $ManNum[$N] ;人名编号
Global $MapString="" ;关系影射表
Local $count=0 ;记录查询的次数
Global $RandEnd=$N-1
For $i=0 To $N-1 Step 1 ;数字列表赋值
$XB[$i]=$i+1
Next
For $i=0 To $N-1 Step 1 ;给所有人随机编号.
Local $j=0
$j=Random(0,$RandEnd,1) ;随机一个数
$RandEnd-=1 ;随即数的最大值减一,因为数组中已经剔除了一个元素.
$ManNum[$i]="Man"&$XB[$j] ;从数字列表中取出随机到的元素并将其赋给人名编号数组.
For $m=$j To $N-2 Step 1 ;从随机的元素开始,将后面的所有元素向前移位,达到剔除随机到的元素的目的.
$XB[$m]=$XB[$m+1]
Next
Next
For $i=0 To $N-1 Step 1 ;生成关系影射表.
For $j=$i To $N-1 Step 1
;个人认为,要是名人只需要所有人认识他就可以了.由于认识关系是单方向的,别人认识他,他肯定不认识别人.
;他自己如果不认识自己就是白痴了.
;条件影射表生成:如果MAN1-->MAN2,MAN1-->MAN3, 则,MAN2--/>MAN1,MAN3--/>MAN1.
If $i<>$j Then $MapString&=$ManNum[$i]&"--/>"&$ManNum[$j]&$ManNum[$j]&"-->"&$ManNum[$i]&"|"
Next
Next
;输入你想查询的人的编号.
$supman=InputBox("输入人名编号","只需要输入数字就可以.","","",200,80)
$Start=TimerInit()
FindSupperMan($supman,False)
Func FindSupperMan($num,$flg)
For $k=0 To $N-1 Step 1 ;从关系影射表中查找必要的关系,别人认识他 他不认识别人.
$tempstr="Man"&$num&"--/>"&$ManNum[$k]&$ManNum[$k]&"-->"&"Man"&$num
If StringInStr($MapString,$tempstr) Then
$count+=1 ;如果查找到了,则查到次数加1.
EndIf
If StringInStr($MapString,"Man"&$num&"-->"&$ManNum[$k]) Then ExitLoop
Next
;如果查到次数等于小镇人数减去他自己,那么就证明所有人都认识他, 他就是名人. 否则不是.
;由于本程序的限制,名人就是数组$ManNum[1]. 只需要输入数组第一个元素的人名编号就可以了。
If $flg=False Then
If $count=$N-1 Then
MsgBox(0,"提示--耗时:"&TimerDiff($Start),"你输入的Man"&$num&" 是名人")
Else
MsgBox(0,"提示--耗时:"&TimerDiff($Start),"你输入的Man"&$num&" 不是名人!")
EndIf
ElseIf $flg=True Then
If $count=$N-1 Then
MsgBox(0,"提示--耗时:"&TimerDiff($Start),"计算机自动查找到名人为:Man"&$num)
EndIf
EndIf
EndFunc
;然后计算机自动查找名人.
$Start=TimerInit()
For $i=1 To $N Step 1
$count=0
FindSupperMan($i,True)
If $count=$N-1 Then ExitLoop
Next
_ArrayDisplay($ManNum,"人名列表信息")