AU3编程解应用题1:输出人际关系网络
本帖最后由 pusofalse 于 2010-5-25 02:01 编辑某小镇上有n个人(2<=n<=50),他们从0至n-1编号。在小镇中,一些人认识另一些人,这种认识关系是单向的(即,如果a认识b和c,那么b和c必然不认识a;如果c不认识d和e,那么d和e可能认识c,也可能不认识c)。
题1,编程输出这种人际网络。
前提条件如上。另外,小镇上有一个名人,当且仅当所有人都认识他,而除他自己之外的n-1个人,他都不认识。而你只能用诸如“a是否认识b?”、“d是否认识a?”的询问,判断出谁是名人。
题2,用不超过100次的询问找出这个名人的编号。
题目要求:
尽量不生成任何临时文件,代码简洁并高效。
可以用Random函数赋一个随机编号给名人,但不能直接输出这个随机值。
题1不受题2干扰。 本帖最后由 lanfengc 于 2010-5-21 19:47 编辑
计算机自动遍历查找50个人的村庄需要查询2500次。 如果你自己输入,查询50次。
;~ 分析。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)
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
Next
;如果查到次数等于小镇人数减去他自己,那么就证明所有人都认识他, 他就是名人. 否则不是.
;由于本程序的限制,名人就是数组$ManNum.只需要输入数组第一个元素的人名编号就可以了。
If $flg=False Then
If $count=$N-1 Then
MsgBox(0,"提示","你输入的Man"&$num&" 是名人")
Else
MsgBox(0,"提示","你输入的Man"&$num&" 不是名人!")
EndIf
ElseIf $flg=True Then
If $count=$N-1 Then
MsgBox(0,"提示","计算机自动查找到名人为:Man"&$num)
EndIf
EndIf
EndFunc
;然后计算机自动查找名人.
For $i=1 To $N Step 1
$count=0
FindSupperMan($i,True)
If $count=$N-1 Then ExitLoop
Next
_ArrayDisplay($ManNum,"人名列表信息") 脑壳晕了,,,,夜深的时候再认真看看! 题1:
$t = TimerInit ()
Dim $max = 50,$aRals [$max]
For $i=0 To $max-1
$aRals[$i] = $i
$knownum = Random(0,$max-1,1);随机生成认识的人数范围
$knowman = -1
For $j=1 To $knownum
$knowman = Int(Random($knowman+1,$max))
If $aRals[$i] <> $knowman Then
If StringInStr ($aRals[$knowman],$aRals[$i]) Then ContinueLoop
$aRals[$i] &= $knowman&" "
Else
$aRals[$i] = ""
EndIf
If $knowman >= $max-10 Then ExitLoop
Next
Next
$result = ""
For $i=0 To 49
$know = $aRals[$i]
If $know == "" Then
$result &= $aRals[$i]&@TAB&"一个人都不认识"& @CRLF
Else
$result &= $aRals[$i]&@TAB&"认识"&@TAB&$know& @CRLF
EndIf
Next
MsgBox (0,"人际网络用时"&TimerDiff ($t),$result)
题2:
$t = TimerInit ()
Dim $max = 50,$aRals [$max]
Dim $mingren = Random(0,$max-1,1)
For $i=0 To $max-1
$aRals[$i] = $i
If $i == $mingren Then ContinueLoop
$knownum = Random(0,$max-1,1);随机生成认识的人数范围
$knowman = -1
$aRals[$i] = $mingren & ""
For $j=1 To $knownum
$knowman = Int(Random($knowman+1,$max))
If $aRals[$i] <> $knowman Then
If StringInStr ($aRals[$knowman],$aRals[$i]) Then ContinueLoop
If $knowman == $mingren Then ContinueLoop
$aRals[$i] &= $knowman&" "
Else
$aRals[$i] &= ""
EndIf
If $knowman >= $max-10 Then ExitLoop
Next
Next
$result = ""
For $i=0 To 49
$know = $aRals[$i]
If $know == "" Then
$result = $i
ExitLoop
EndIf
Next
MsgBox (0,"名人号码用时"&TimerDiff ($t),"随机生成的名人是:"&$mingren & @CRLF &"查找出的名人是:"&$result)
论坛出错了???我发的优化算法后的代码呢???
幸好我保存了。 再发一次。;~ 分析。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.只需要输入数组第一个元素的人名编号就可以了。
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,"人名列表信息") P版的代码什么时候贴上来?贴上来学习一下思路啊。 本帖最后由 pusofalse 于 2010-5-23 20:37 编辑
抱歉啊,这两天在忙些其他的事情,没及时上来看。
这是我的解:
Q1:#include <Array.au3>
Local $iTimer = TimerInit(), $iMaxNumber = Random(2, 50, 1)
Local $aRelation[$iMaxNumber][$iMaxNumber]
For $i = 0 To $iMaxNumber - 1
For $j = 0 To $iMaxNumber - 1
If ($i <> $j) Then
If ($aRelation[$j][$i]) Then
$aRelation[$i][$j] = 0
Else
$aRelation[$i][$j] = Random(0, 1, 1)
EndIf
EndIf
Next
Next
_Arraydisplay($aRelation, TimerDiff($iTimer))用0表示不认识,1表示认识,人际关系呈现在一个矩阵中。
Q2:#include <Array.au3>
Local $iTimer = TimerInit()
Local $iMaxNumber = Random(2, 50, 1)
Local $aRelation[$iMaxNumber][$iMaxNumber]
Local $iFamous = Random(0, $iMaxNumber - 1, 1), $iFamousSearched = 0
For $i = 0 To $iMaxNumber - 1
For $j = 0 To $iMaxNumber - 1
If ($i <> $j) Then
If ($aRelation[$j][$i]) Then
$aRelation[$i][$j] = 0
Else
$aRelation[$i][$j] = Random(0, 1, 1)
EndIf
EndIf
Next
Next
For $i = 0 To $iMaxNumber - 1
If ($i <> $iFamous) Then
$aRelation[$iFamous][$i] = 0
$aRelation[$i][$iFamous] = 1
EndIf
Next
For $i = 0 To $iMaxNumber - 1
If ($aRelation[$iFamousSearched][$i]) Then $iFamousSearched = $i
Next
_Arraydisplay($aRelation, $iFamous & " " & $iFamousSearched)_Arraydisplay的标题中,$iFamous表示随机生成的名人编号,$iFamousSearched表示通过询问获取的名人编号。 回复 8# pusofalse
代码很精彩,用矩阵来处理关系,学习了。 顶贴、回帖、拿分、走人!url
页:
[1]