本帖最后由 老刘1号 于 2019-4-22 13:58 编辑
其实是个老算法题了,今天看到群里有人提起,就来发个帖子,
据说著名犹太历史学家 Josephus 有过以下的故事:在罗马人占
领乔塔帕特后,39 个犹太人与 Josephus 及他的朋友躲到一个洞中,
39 个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方
式:41 个人围成一个圆圈,由第 1 个人开始报数,报数到第 3 个人,
该人就必须自杀,然后再由下一个重新报数,报数到的第 3 个人,该
人又自杀...直到所有人都自杀身亡为止,然而 Josephus 和他的朋友
并不想遵从。
一开始有 i 个人,数 j 去 1,最后剩余 k 个人。首先从一个人开
始,越过 j-1 个人,并杀掉第 j 个人;接着再越过 j-1 个人,并杀掉
第 j 个人...这个过程沿着圆圈一直进行,直到最终只剩下 k 个人,这
k 个人就可以继续活着。问题是,给定了 i、j、k 值,一开始要站在
什么地方才能避免被处决?聪明的Josephus要他的朋友先假装遵从,
他将朋友与自己安排在第 16 个与第 31 个位置,于是逃过了这场死亡
游戏。
汇编-一维数组版 | ;约瑟夫问题(一维数组) Algo | | ;Code By 老刘 | | ;环境:MASM32 SDK | | ;编译指令:ml /coff 约瑟夫问题(一维数组).asm /link /subsystem:console | | ;参数:总人数、保留人数、每n个人杀一次的n(小于总人数)。 | | ;参数最大值:999999。 | | ;参考:MHL批处理标准教程之约瑟夫问题。 | | | | | | Include masm32rt.inc | | Main Proto | | | | .Data? | | bBuffer DB 999999 Dup (?) | | dwAll DD ? | | dwPersist DD ? | | bBuffer2 DB 11 Dup (?) | | dwCrLfZero DD ? | | dwJumpPlusOne DD ? | | ;End Data? | | | | .Code | | Main Proc | | ;获得参数 | | Invoke ArgClC,1,Offset bBuffer2 | | Sub Esp,4 | | Invoke atodw_ex,Offset bBuffer2 | | Add Esp,4 | | Mov dwAll,Eax | | Invoke ArgClC,2,Offset bBuffer2 | | Sub Esp,4 | | Invoke atodw_ex,Offset bBuffer2 | | Add Esp,4 | | Mov dwPersist,Eax | | Invoke ArgClC,3,Offset bBuffer2 | | Sub Esp,4 | | Invoke atodw_ex,Offset bBuffer2 | | Add Esp,4 | | Mov dwJumpPlusOne,Eax | | | | ;开始标记 | | Lea Ebx,bBuffer | | Add Ebx,dwAll | | Mov Edx,dwAll | | Lea Esi,bBuffer | | Mov Edi,Esi | | Xor Eax,Eax | | .While Edx != dwPersist | | Mov Ecx,dwJumpPlusOne | | .Repeat | | LodSB | | Add Ecx,Eax | | .If Esi == Ebx | | Mov Esi,Edi | | .EndIf | | .UntilCxZ | | .If Esi == Edi | | Mov Byte Ptr [Ebx-1],1 | | .Else | | Dec Esi | | Mov Byte Ptr [Esi],1 | | Inc Esi | | .EndIf | | Dec Edx | | .EndW | | | | ;输出 | | Mov dwCrLfZero,000D0AH | | Xor Ecx,Ecx | | Lea Esi,bBuffer | | Dec Esi | | .While Ecx != dwAll | | Inc Ecx | | .If Byte Ptr [Esi+Ecx] == 0 | | Pushad | | Invoke dw2a,Ecx,Offset bBuffer2 | | Invoke StdOut,Offset bBuffer2 | | Invoke StdOut,Offset dwCrLfZero | | Popad | | .EndIf | | .EndW | | | | Ret | | Main EndP | | | | Start: | | Call Main | | Invoke ExitProcess,NULL | | End Start | | EndCOPY |
汇编-单向循环链表版 | ;约瑟夫问题(单向循环链表) Algo | | ;Code By 老刘 | | ;环境:MASM32 SDK | | ;编译指令:ml /coff 约瑟夫问题(单向循环链表).asm /link /subsystem:console | | ;参数:总人数、保留人数、每n个人杀一次的n(小于总人数)。 | | ;参数最大值:1227。 | | ;参考:MHL批处理标准教程之约瑟夫问题。 | | | | | | Include masm32rt.inc | | Main Proto | | | | OneWayLinkedList Struct | | Data DWord ? | | Next DWord ? | | OneWayLinkedList EndS | | | | .Data? | | dwAll DD ? | | dwPersist DD ? | | dwJump DD ? | | bBuffer2 DB 11 Dup (?) | | dwCrLfZero DD ? | | dwLinkedListHead DD ? | | ;End Data? | | | | .Code | | Main Proc | | ;获得并处理参数 | | Invoke ArgClC,1,Offset bBuffer2 | | Sub Esp,4 | | Invoke atodw_ex,Offset bBuffer2 | | Add Esp,4 | | Mov dwAll,Eax | | Invoke ArgClC,2,Offset bBuffer2 | | Sub Esp,4 | | Invoke atodw_ex,Offset bBuffer2 | | Add Esp,4 | | Mov dwPersist,Eax | | Invoke ArgClC,3,Offset bBuffer2 | | Sub Esp,4 | | Invoke atodw_ex,Offset bBuffer2 | | Add Esp,4 | | Dec Eax | | Mov dwJump,Eax | | | | ;创建链表 | | Assume Ebx:Ptr OneWayLinkedList | | Assume Eax:Ptr OneWayLinkedList | | Invoke Alloc,SizeOf OneWayLinkedList | | Mov dwLinkedListHead,Eax | | Mov Ecx,dwAll | | Dec Ecx | | Xor Edx,Edx | | .Repeat | | Mov Ebx,Eax | | Inc Edx | | Push Ecx | | Push Edx | | Invoke Alloc,SizeOf OneWayLinkedList | | Pop Edx | | Pop Ecx | | Mov [Ebx].Next,Eax | | Mov [Ebx].Data,Edx | | .UntilCxZ | | Mov Ebx,Eax | | Inc Edx | | Push dwLinkedListHead | | Pop [Ebx].Next ;指向链表结点1 | | Mov [Ebx].Data,Edx | | ;此时Ebx指向尾结点 | | | | ;开始标记 | | Mov Edx,dwAll | | .While Edx != dwPersist | | Mov Ecx,dwJump | | .If Ecx != 0 | | .Repeat | | Mov Ebx,[Ebx].Next | | .UntilCxZ | | .EndIf | | Mov Eax,[Ebx].Next | | Mov Ecx,[Eax].Next | | Mov [Ebx].Next,Ecx | | Push Edx | | Invoke Free,Eax | | Pop Edx | | Dec Edx | | .EndW | | | | ;遍历链表并输出 | | Mov dwCrLfZero,000D0AH | | Mov Ecx,Ebx | | .Repeat | | Pushad | | Invoke dw2a,[Ebx].Data,Offset bBuffer2 | | Invoke StdOut,Offset bBuffer2 | | Invoke StdOut,Offset dwCrLfZero | | Popad | | Mov Ebx,[Ebx].Next | | .Until Ebx == Ecx | | Assume Ebx:Nothing | | Assume Eax:Nothing | | | | Ret | | Main EndP | | | | Start: | | Call Main | | Invoke ExitProcess,NULL | | End Start | | EndCOPY |
PowerShell | [int] $total=Read-Host -Prompt "请输入人数:"; | | [int] $remain=Read-Host -Prompt "请输入保留人数:"; | | [int] $step=Read-Host -Prompt "每隔几个人?:"; | | $counter=$step; | | $arr=[int]1..$total; | | $arrcount=$arr.Count; | | | | while($total -gt $remain) | | { | | for($i=0;$i -lt $arrcount;$i++) { | | if($arr[$i] -ne 0){$counter--} | | if($counter -eq 0){ | | $arr[$i]=[int] 0; | | $counter=$step; | | $total--; | | } | | if($total -le $remain){break} | | } | | } | | | | foreach($s in $arr){ | | if($s -ne 0){$s} | | } | | pause;COPY |
|