Josephus环

约瑟夫问题是个有名的问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,被杀掉的人的序号为5,4,6,2,3。最后剩下1号。

方法一.a

Option Explicit
'用元素循环的方法解决Joseph环的问题
Sub Joseph_1()
'定义元素长度,关键值
Dim m&, n&
'定义元素数组,变量
Dim arrM(), iM&
'定义计数项,累计出圈数
Dim iCount&, jCount&
'输出过程数组,变量
Dim arrOut(), mOut&, nOut&
'====================================
With Sheet2
m = .Cells(2, 2)
n = .Cells(3, 2)
ReDim arrM(1 To m)
  For iM = 1 To m
    arrM(iM) = iM    '数组初始化为0
  Next
iCount = 0  '初始化计算项
jCount = 0
ReDim arrOut(1 To m, 1 To m)
'------------------循环-----------------------------
Do Until jCount = m - 1
  For iM = 1 To m
   If arrM(iM) <> 0 Then    '排除已经移除项
    iCount = iCount + 1
     If iCount = n Then     '计数=值
      arrM(iM) = 0
      iCount = 0
      jCount = jCount + 1
      '-----输出过程数组-----------------------
       For mOut = 1 To m
         arrOut(jCount, mOut) = arrM(mOut)
       Next
      '-----------------------------------------
     End If
    End If
  Next
Loop
'-------------------输出-------------------------
.[A12].CurrentRegion.Clear
.[A12].Resize(UBound(arrOut), m) = arrOut
End With
'====================================
End Sub

方法一.b

Option Explicit
'用collection建立单循环链表的方式解决Josephus环
Sub Joseph_2()
'定义集合,变量
Dim cM As Collection, iC&
'定义元素长度,关键值
Dim m&, n&
'定义collection指针,计数量,界限
Dim sp&, iCount&, Limit&
'输出过程数组,变量
Dim arrOut(), mOut&, nOut&
'=========================================
Set cM = New Collection
With Sheet3
m = .Cells(2, 2)
n = .Cells(3, 2)
'-----------------------------------------
For iC = 1 To m
  cM.Add iC  '数据读入集合
Next
ReDim arrOut(1 To m, 1 To m)
'----------------------------------------
iC = 0      '初始化collection变量
iCount = 0  '初始化计数项
sp = 0      '初始化指针
'Limit = cM.Count    '初始化界限
Do
    sp = sp + 1   '指针移+1
    If sp > cM.Count Then
     sp = 1
    End If
    iCount = iCount + 1   '计算项+1
    If iCount = n Then    '如果点数=关键值
     cM.Remove (sp)     '移除
     iCount = 0         '重新初始化计数项
     sp = sp - 1        '指针移回前一数据项
'-----输出过程数组------------------------
      mOut = mOut + 1
       For iC = 1 To cM.Count
         arrOut(mOut, iC) = cM.Item(iC)
       Next
   End If
'------------------------------------------
  If cM.Count = 1 Then Exit Do  '退出循环
Loop
'--------------输出---------------------------
.[A12].CurrentRegion.Clear
.[A12].Resize(UBound(arrOut), m) = arrOut
End With
'=========================================
End Sub

方法二

Option Explicit

'用数学归纳法 , 递归公式进行计算
'递归公式:g(n,k)=((g(n-1,k)+k-1) mod n)+1
'n为总人数,k为关键字段
'公式来源
'https://en.wikipedia.org/wiki/Josephus_problem
Sub Joseph_3()
Dim m&, n&, r&    '定义变量
With Sheet4
m = .Cells(2, 2)     '人数
n = .Cells(3, 2)     '报数
Sheet1.Cells(21, 4) = Josephus(m, n)    '输出结果

End With
End Sub

Function Josephus(n, k)
'n为人数;k为报数
If n = 1 Then
  Josephus = 1      '递归出口
Else
  Josephus = ((Josephus(n - 1, k) + k - 1) Mod n) + 1   '递归公式
End If
End Function



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值