'=================================================
'CBoxs.cls
'=================================================
Private m_Boxes() As CBox
Public Property Let NewBox(value As CBox)
ReDim Preserve m_Boxes(UBound(m_Boxes) + 1) As CBox
Set m_Boxes(UBound(m_Boxes)) = value
End Property
Public Property Get LeftContains(ByVal Index As Long) As Long
Dim i As Long
Dim pBox As CBox
For i = Index + 1 To UBound(m_Boxes)
Set pBox = m_Boxes(i)
LeftContains = LeftContains + pBox.nMax * pBox.nNum
Next i
End Property
Public Function Div(ByVal nBall As Long) As String
Dim i As Long
Dim dNum As Double
Dim nDivBall As Long
nDivBall = nBall
'check if has enough space
If LeftContains(0) < nDivBall Then
Div = "the ball number larger than all boxes' space "
Exit Function
End If
For i = 1 To UBound(m_Boxes)
If m_Boxes(i).nMax * m_Boxes(i).nNum >= nDivBall Then
dNum = ndivall / Format(m_Boxes(i).nMax, "#.0000")
dNum = CLng(dNum) + IIf(CLng(dNum) - num = 0, 0, 1)
If dNum = 0 Then dNum = 1
Div = Div & "Type:" & m_Boxes(i).nMax & "----" & dNum & vbCrLf
Exit Function
Else
Div = Div & "Type:" & m_Boxes(i).nMax & "----" & m_Boxes(i).nNum & vbCrLf
nDivBall = nDivBall - m_Boxes(i).nMax * m_Boxes(i).nNum
End If
Next i
End Function
Private Sub Class_Initialize()
ReDim m_Boxes(0) As CBox
End Sub
'========================================
'CBox.cls
'========================================
Public nMax As Long ' max contain number
Public nNum As Long 'number of these boxes
'=======================
'Form1.frm
'========================
Private Sub Command1_Click()
Dim nBall
Dim pBox As CBox
Dim objBoxs As New CBoxs
Set pBox = New CBox
pBox.nMax = 200
pBox.nNum = 1
objBoxs.NewBox = pBox
Set pBox = New CBox
pBox.nMax = 150
pBox.nNum = 1
objBoxs.NewBox = pBox
Set pBox = New CBox
pBox.nMax = 100
pBox.nNum = 1
objBoxs.NewBox = pBox
Set pBox = New CBox
pBox.nMax = 80
pBox.nNum = 1
objBoxs.NewBox = pBox
nBall = 440
MsgBox objBoxs.Div(nBall)
End Sub
用递归的办法遍历所有装箱可能,然后找出用箱子最少并且剩余空间最小的方案。关键看着两个条件的优先级哪个高。比如说360个球,最少箱子的方案是两个200的箱子,最少浪费空间的方案是一个200的两个80的。
我下面给出的代码是以最少箱子的优先级更高
'LeftBall:剩余未装箱球的数量,第一次传入球的总数
'arybox: 传入箱子数组
'begin: 第一次传入的标志,第一次传入true
'BoxSel: 递归过程中传递的参数,不必传入
Private Function test(ByVal LeftBall As Integer, ByVal arybox As Variant, begin As Boolean, Optional ByVal BoxSel As String) As String
Static BestSel As String
Static BestSpaceLeft As Integer
Static BestCount As Integer
Dim i As Integer
Dim tmpLeftBall As Integer
Dim tmpBoxSel As String
Dim tmpCount As Integer
If begin Then
BestSel = ""
BestSpaceLeft = 400
BestCount = 100
End If
For i = LBound(arybox) To UBound(arybox)
DoEvents
tmpLeftBall = LeftBall - arybox(i)
tmpBoxSel = BoxSel & i & " "
If tmpLeftBall <= 0 Then
tmpCount = Len(tmpBoxSel) / 2
If tmpCount <= BestCount Then
If Abs(tmpLeftBall) <= BestSpaceLeft Then
BestSpaceLeft = Abs(tmpLeftBall)
BestSel = tmpBoxSel
BestCount = tmpCount
End If
End If
'Debug.Print tmpBoxSel
Else
Call test(tmpLeftBall, arybox, False, tmpBoxSel)
End If
Next
test = BestSel
End Function
调用举例:
Dim arybox(1 To 4) As Integer
arybox(1) = 200
arybox(2) = 150
arybox(3) = 100
arybox(4) = 80
Debug.Print test(440, arybox, True)
Debug.Print test(360, arybox, True)
Debug.Print test(501, arybox, True)
输出:
3 2 1
1 1
2 1 1
440个球3号箱子用一个2号箱子用一个1号箱子用一个
360个球1号箱子用两个
501个球2号一个一号两个,剩余空间49
联系客服