称球问题实现(vb)

这是一个使用VB编程解决经典称球问题的程序,目标是在三次称量内确定十二个外观相同但有一个重量不同的球。通过分块穷举法和递归调用来确定不同情况下的球重,确保在三次称量后能确定哪个球是坏球以及其重量状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

VB源码供大家参考
这个程序编起来挺麻烦的,goto都用上了
VERSION 5.00
Begin VB.Form Form1
   Caption         =   "Form1"
   ClientHeight    =   6960
   ClientLeft      =   165
   ClientTop       =   735
   ClientWidth     =   9900
   LinkTopic       =   "Form1"
   ScaleHeight     =   6960
   ScaleWidth      =   9900
   StartUpPosition =   3  'Windows Default
   Begin VB.TextBox Text1
      Height          =   6840
      Left            =   30
      MultiLine       =   -1  'True
      ScrollBars      =   3  'Both
      TabIndex        =   0
      Top             =   60
      Width           =   9840
   End
   Begin VB.Menu start
      Caption         =   "start"
   End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
'问题描述:
'有十二个外表相同的球,其中有一个坏球,它的重量和其它十
'一个有轻微的(但是可以测量出来的)差别。现在有一架没有砝码的
'很灵敏的天平,问如何称三次就保证找出那个坏球,并知道它比标准
'球重还是轻。
Option Explicit
'分块穷举法
Dim BallData(3, 2, 5) As Long     '各次取球数据,最多取5个
Dim WeightResult(3) As Long       '3次称球结果 -1 左轻 0 相等  1 左重

Private Ball(12) As Long          ' 小球重 ,值为0 、1 或 -1 ,分别表示正常球 比其它球重 比其它球轻
Private BallValue(12) As Long     ' 冲突检测值 第一取球前置1,取球值后左+10,右+100 第二次取值后左+1000 右+10000

Private PartCount As Long         '分组数
Private PartArray(12, 12) As Long  '各组小球数据
Private PartNum(12)     As Long   '各组小球个数
Private PartGeted(12) As Long    '各组已被取的小球个数
Private PartGeted2(12) As Long    '各组已被取的小球个数
Private BallNum As Long, GetedNum As Long

'需要定义3个以避免数据冲突
Private ArrayDataCount(3) As Long
Private ArrayData(3, 10000, 2, 5) As Long

Private Get1 As Long, Get2 As Long

Private ResultArray(3, 3, 3, 2, 5) As Long '存放3次取值结果
'为了减少变量个数,使用多维数组,各维表示次数、WeightResult(1)、WeightResult(2)、L/R、BallData
'有效数据为        (1 1 1)
'      (2 1 1)    (2 2 1)     (2 3 1)
' (311 312 313) (321 322 323)  (331 332 333)

Private Sub Form_Resize()
    Text1.Move 0, 0, Me.ScaleWidth, Me.ScaleHeight
End Sub

Private Sub start_Click() 'ok
    MainProc (0)
End Sub

Public Function MainProc(ByVal iStep As Long) As Boolean
'启动 MainProc(0)
    Dim i As Long, j As Long, k As Long
    Dim Num As Long, Sum As Long, OK As Boolean
   
    MainProc = False
    Num = GetNum(iStep) '基于0
   
    If Num > 3 ^ (3 - iStep) Then Exit Function
   
    iStep = iStep + 1
    GetArray iStep
   
    For i = 1 To ArrayDataCount(iStep)  '基于1,取1 2 3共3组小球
        '合法检测
       
        Call SetArray(iStep, i)           '设置取球数据BallData(iStep,,)
        WeightResult(iStep) = -1          '设置结果    WeightResult(iStep)
        Num = GetNum(iStep)
        If Num > 3 ^ (3 - iStep) Then GoTo nexti
        WeightResult(iStep) = 0
        Num = GetNum(iStep)
        If Num > 3 ^ (3 - iStep) Then GoTo nexti
        WeightResult(iStep) = 1
        Num = GetNum(iStep)
        If Num > 3 ^ (3 - iStep) Then GoTo nexti
       
        If iStep < 3 Then '没有取满
            WeightResult(iStep) = -1        '设置结果
            If Not MainProc(iStep) Then GoTo nexti
            WeightResult(iStep) = 0
            If Not MainProc(iStep) Then GoTo nexti
            WeightResult(iStep) = 1
            If Not MainProc(iStep) Then GoTo nexti
        End If
       
        Call SetResult(iStep, i)   ' 根据iStep、BallData(iStep,,)、WeightResult(iStep)设置取球结果(13对)
        MainProc = True
       
        If iStep = 1 Then
            PrintResult
        End If
       
        Exit Function    '这里不退出,并且SetResult改为保存所有取法,即可得到所有组合
nexti:
    Next i
End Function

'Completed
Public Function GetNum(ByVal iStep As Long) As Long
'根据BallData(3, 2, 5)、WeightResult取得需要推出的结果数
'第一次取球为GetNum(0)=24
    Dim i As Long, j As Long, k As Long
    Dim Num As Long, Sum As Long, OK As Boolean
   
    For i = 0 To 12: Ball(i) = 0: Next
   
    Num = 24 '最多24个符合
    For i = 1 To 12
        Ball(i - 1) = 0
        Ball(i) = 1  '第i个球重
       
        For k = 1 To iStep
            Sum = 0
            For j = 1 To 5
                Sum = Sum + Ball(BallData(k, 1, j)) - Ball(BallData(k, 2, j))
            Next
            If Sum <> WeightResult(k) Then
                Num = Num - 1
                Exit For
            End If
        Next
    Next i
    Ball(12) = 0
    For i = 1 To 12
        Ball(i - 1) = 0
        Ball(i) = -1  '第i个球重
       
        For k = 1 To iStep
            Sum = 0
            For j = 1 To 5
                Sum = Sum + Ball(BallData(k, 1, j)) - Ball(BallData(k, 2, j))
            Next
            If Sum <> WeightResult(k) Then
                Num = Num - 1
                Exit For
            End If
        Next
    Next i
    GetNum = Num
End Function

'Completed
Public Function GetArray(ByVal iStep As Long)  '根据前iStep次取球,列出所有不重复取球组合
    Dim i As Long, j As Long
    Dim OK As Boolean
   
    SetBall iStep - 1
    GetPart
   
    ArrayDataCount(iStep) = 0
       
    For i = 1 To 5
        BallNum = i
        GetArrayByNum iStep, 1, i
    Next i
End Function

'Completed
Public Function GetArrayByNum(ByVal iStep As Long, ByVal Part As Long, ByVal Num As Long) As Boolean
    Dim i As Long, j As Long
    Dim OK As Boolean
   
    PartGeted(Part) = 0
   
    If Num = 0 Then  '结束
        GetedNum = 0
        For i = 1 To Part - 1
            For j = 1 To PartGeted(i)
                GetedNum = GetedNum + 1
                ArrayData(iStep, 0, 1, GetedNum) = PartArray(i, j)   '临时存放于ArrayData(iStep, 0, 1,)
            Next j
        Next i
        GetArrayByNum2 iStep, 1, BallNum
        Exit Function
    End If
       
    If Part > PartCount Or Num < 0 Then
        Exit Function
    End If
       
    For i = 0 To 5
        If i <= PartNum(Part) Then
            PartGeted(Part) = i
            GetArrayByNum iStep, Part + 1, Num - i
        Else
            Exit For
        End If
    Next i
End Function

'Completed
Public Function GetArrayByNum2(ByVal iStep As Long, ByVal Part As Long, ByVal Num As Long) As Boolean
    Dim i As Long, j As Long
    Dim OK As Boolean
   
    PartGeted2(Part) = 0
   
    If Num = 0 Then  '结束
        ArrayDataCount(iStep) = ArrayDataCount(iStep) + 1
        GetedNum = 0
        For i = 0 To 5
            ArrayData(iStep, ArrayDataCount(iStep), 1, i) = 0
            ArrayData(iStep, ArrayDataCount(iStep), 2, i) = 0
        Next i
        For i = 1 To Part - 1
            For j = 1 To PartGeted2(i)
                GetedNum = GetedNum + 1
                ArrayData(iStep, ArrayDataCount(iStep), 1, GetedNum) = ArrayData(iStep, 0, 1, GetedNum)
                ArrayData(iStep, ArrayDataCount(iStep), 2, GetedNum) = PartArray(i, j + PartGeted(i))
            Next j
        Next i
        Exit Function
    End If
       
    If Part > PartCount Or Num < 0 Then
        Exit Function
    End If
       
    For i = 0 To 5
        If i <= PartNum(Part) - PartGeted(Part) Then
            PartGeted2(Part) = i
            GetArrayByNum2 iStep, Part + 1, Num - i
        Else
            Exit For
        End If
    Next i
End Function

'Completed
Public Function GetPart() '根据BallValue取得分组数据
    Dim i As Long, j As Long
    Dim OK As Boolean
   
    PartCount = 0
   
    For i = 1 To 12
        OK = False
        For j = 1 To PartCount
            If BallValue(PartArray(j, 1)) = BallValue(i) Then
                OK = True
                PartNum(j) = PartNum(j) + 1
                PartArray(j, PartNum(j)) = i
                Exit For
            End If
        Next
        If Not OK Then
            PartCount = PartCount + 1
            PartNum(PartCount) = 1
            PartArray(PartCount, 1) = i
        End If
    Next
End Function

'Completed
Public Function SetBall(iStep As Long) '设置BallValue(12)
    Dim i As Long, j As Long
    Dim Value As Long
   
    For i = 1 To 12
        BallValue(i) = 1
    Next i
   
    For i = 1 To iStep
        Value = 100 ^ i / 10
        If WeightResult(i) = 0 Then
            For j = 1 To 5
                BallValue(BallData(i, 1, j)) = BallValue(BallData(i, 1, j)) + Value
                BallValue(BallData(i, 2, j)) = BallValue(BallData(i, 2, j)) + Value
            Next
        Else
            For j = 1 To 5
                BallValue(BallData(i, 1, j)) = BallValue(BallData(i, 1, j)) + Value
                BallValue(BallData(i, 2, j)) = BallValue(BallData(i, 2, j)) + Value * 10
            Next
        End If
    Next
End Function
'未测试
Public Sub SetArray(ByVal iStep As Long, ByVal Num As Long)
'设置取球数据BallData(iStep,,)
    Dim i As Long, j As Long
       
    For i = 1 To 5
        BallData(iStep, 1, i) = ArrayData(iStep, Num, 1, i)
        BallData(iStep, 2, i) = ArrayData(iStep, Num, 2, i)
    Next i
End Sub

Public Sub SetResult(ByVal iStep As Long, ByVal Num As Long)
'设置取数结果
    Dim i As Long, j As Long
   
    If iStep = 1 Then
        For i = 1 To 5
            ResultArray(1, 1, 1, 1, i) = ArrayData(iStep, Num, 1, i)
            ResultArray(1, 1, 1, 2, i) = ArrayData(iStep, Num, 2, i)
        Next
    ElseIf iStep = 2 Then
        For i = 1 To 5
            ResultArray(2, WeightResult(1) + 2, 1, 1, i) = ArrayData(iStep, Num, 1, i)
            ResultArray(2, WeightResult(1) + 2, 1, 2, i) = ArrayData(iStep, Num, 2, i)
        Next
    ElseIf iStep = 3 Then
        For i = 1 To 5
            ResultArray(3, WeightResult(1) + 2, WeightResult(2) + 2, 1, i) = ArrayData(iStep, Num, 1, i)
            ResultArray(3, WeightResult(1) + 2, WeightResult(2) + 2, 2, i) = ArrayData(iStep, Num, 2, i)
        Next
    End If
End Sub

'输出结果
Public Function PrintResult()
    Dim ls As String, rs As String, s As Variant
    Dim i As Long, j As Long, k As Long
    Const SP As Long = 30
    s = Array("<", "=", ">")
' 1
    ls = "":  rs = ""
    For i = 1 To 5
        BallData(1, 1, i) = ResultArray(1, 1, 1, 1, i)
        BallData(1, 2, i) = ResultArray(1, 1, 1, 2, i)
        If ResultArray(1, 1, 1, 1, i) <> 0 Then
            ls = ls & ResultArray(1, 1, 1, 1, i)
            rs = rs & ResultArray(1, 1, 1, 2, i)
        End If
    Next i
    Text1.Text = Text1.Text & ls & " V " & rs & vbCrLf
   
    For i = 1 To 3
        WeightResult(1) = i - 2
        ls = "":  rs = ""
        For j = 1 To 5
            BallData(2, 1, j) = ResultArray(2, i, 1, 1, j)
            BallData(2, 2, j) = ResultArray(2, i, 1, 2, j)
            If ResultArray(2, i, 1, 1, j) <> 0 Then
                ls = ls & ResultArray(2, i, 1, 1, j)
                rs = rs & ResultArray(2, i, 1, 2, j)
            End If
        Next j
        Text1.Text = Text1.Text & Space(SP) & s(WeightResult(1) + 1) & ls & " V " & rs & vbCrLf
       
        For j = 1 To 3
            WeightResult(2) = j - 2
            ls = "":  rs = ""
            For k = 1 To 5
                BallData(3, 1, k) = ResultArray(3, i, j, 1, k)
                BallData(3, 2, k) = ResultArray(3, i, j, 2, k)
                If ResultArray(3, i, j, 1, k) <> 0 Then
                    ls = ls & ResultArray(3, i, j, 1, k)
                    rs = rs & ResultArray(3, i, j, 2, k)
                End If
            Next
            Text1.Text = Text1.Text & Space(SP * 2) & s(WeightResult(2) + 1) & ls & " V " & rs & vbCrLf
            For k = 1 To 3
                WeightResult(3) = k - 2
                Text1.Text = Text1.Text & Space(SP * 3) & s(WeightResult(3) + 1) & GetResultString & vbCrLf
            Next k
        Next
   
    Next i
End Function

Public Function GetResultString() As String
    Dim i As Long, j As Long, k As Long
    Dim Sum As Long, OK As Boolean
   
    For i = 0 To 12: Ball(i) = 0: Next
   
    For i = 1 To 12
        Ball(i - 1) = 0:  Ball(i) = 1
       
        OK = True
        For k = 1 To 3
            Sum = 0
            For j = 1 To 5
                Sum = Sum + Ball(BallData(k, 1, j)) - Ball(BallData(k, 2, j))
            Next
            If Sum <> WeightResult(k) Then
                OK = False
                Exit For
            End If
        Next
        If OK Then GetResultString = "第" & i & "号球重"
    Next i
    Ball(12) = 0
    For i = 1 To 12
        Ball(i - 1) = 0:  Ball(i) = -1
       
        OK = True
        For k = 1 To 3
            Sum = 0
            For j = 1 To 5
                Sum = Sum + Ball(BallData(k, 1, j)) - Ball(BallData(k, 2, j))
            Next
            If Sum <> WeightResult(k) Then
                OK = False
                Exit For
            End If
        Next
        If OK Then GetResultString = "第" & i & "号球轻"
    Next i
    If GetResultString = vbNullString Then GetResultString = "==========不可能"
End Function

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值