2025年12月29日 星期一

VBA:運輸問題 西北角法與最小直覺法

這篇來聊一下運輸問題裡很常見的「西北角法」。

西北角法的玩法很單純,就是從運輸表左上角(也就是所謂的西北角)開始分配數量,一路往右、往下走,把供給跟需求配到剛好。

西北角法它的好處是:

算法超直覺、步驟固定。

很快就能拼出一個「可行解」,程式也好寫。

念書念到這個,想了一下發願AI,這種規則這麼機械,很適合交給 AI 生個雛形,再用 VBA 包一包來玩看看。

教科書習題:

習題解答:


小編EXCEL 維護:
分配結果與總成本

以下是西北角法的 VBA 範例程式,搭配上面的試題即可直接套用:

Sub NorthwestCornerMethod()
    
    On Error GoTo LINE1
    
    Dim ws As Worksheet    
    
    Set ws = ActiveSheet
    
    ' 設定輸入範圍 (請依實際資料調整)
    Dim supplyRange As Range, demandRange As Range, costRange As Range
    Set supplyRange = ws.Range("E2:E4")  ' 供給: 3供應點
    Set demandRange = ws.Range("B5:D5")  ' 需求: 3需求點
    Set costRange = ws.Range("B2:D4")    ' 運費矩陣 3x3
    
    Dim m As Integer, n As Integer
    m = supplyRange.Rows.Count
    n = demandRange.Columns.Count
    
    ' 讀取資料到陣列
    Dim supply() As Double, demand() As Double, cost() As Double
    Dim allocation() As Double, i As Integer, j As Integer
    
    ReDim supply(0 To m - 1), demand(0 To n - 1)
    ReDim cost(0 To m - 1, 0 To n - 1)
    ReDim allocation(0 To m - 1, 0 To n - 1)
    
    Dim k As Integer
    
    On Error Resume Next
    
    For k = 0 To m - 1
        supply(k) = supplyRange.Cells(k + 1, 1).Value
    Next k
    For k = 0 To n - 1
        demand(k) = demandRange.Cells(1, k + 1).Value
    Next k
    For i = 0 To m - 1
        For j = 0 To n - 1
            cost(i, j) = costRange.Cells(i + 1, j + 1).Value
        Next j
    Next i
    
       On Error GoTo LINE1
    
    ' 西北角法核心演算法
    i = 0: j = 0
    Dim totalCost As Double: totalCost = 0
    
    Do While i < m And j < n
        Dim amount As Double
        amount = WorksheetFunction.Min(supply(i), demand(j))
        
        allocation(i, j) = amount
        totalCost = totalCost + amount * cost(i, j)
        
        supply(i) = supply(i) - amount
        demand(j) = demand(j) - amount
        
        If supply(i) = 0 Then i = i + 1
        If demand(j) = 0 Then j = j + 1
    Loop
    
    ' 輸出結果 (從F2開始)
    ws.Range("G1").Value = "分配結果"
 
    
    For i = 0 To m - 1
        For j = 0 To n - 1
            ws.Cells(i + 2, 7 + j).Value = allocation(i, j)
        Next j
    Next i
    
       ws.Range("H1").Value = "總成本"
    ws.Range("I1").Value = totalCost
    
    MsgBox "西北角法計算完成!總成本: " & Format(totalCost, "0.00")
    
    Exit Sub
    
    
LINE1:
    
    
    MsgBox "ERROR"
    
    Resume
    
End Sub

再來一試:


直覺法:由於西北角法的運輸指派方式完全未將成本列入考量,因此若以成本最小為優先考慮,必將可得較佳之初始值,此種方法又稱最小成本法。
步驟:
1.找尋最低成本的方格,優先滿足。
2.再找次成本最低,以此類推。

案例:

結果:




Sub LeastCostMethod()
    Dim ws As Worksheet: Set ws = ActiveSheet
    Dim supplyRng As Range, demandRng As Range, costRng As Range
    Set supplyRng = ws.Range("E2:E4")    ' 供給
    Set demandRng = ws.Range("B5:D5")    ' 需求
    Set costRng = ws.Range("B2:D4")      ' 成本
    
    Dim m As Integer, n As Integer: m = supplyRng.Rows.Count: n = demandRng.Columns.Count
    Dim supply() As Double, demand() As Double, cost() As Double, allocation() As Double
    ReDim supply(0 To m - 1), demand(0 To n - 1), cost(0 To m - 1, 0 To n - 1), allocation(0 To m - 1, 0 To n - 1)
    
    ' 讀取資料
    Dim i As Integer, j As Integer, k As Integer
    For k = 0 To m - 1: supply(k) = supplyRng.Cells(k + 1, 1).Value: Next
    For k = 0 To n - 1: demand(k) = demandRng.Cells(1, k + 1).Value: Next
    For i = 0 To m - 1
        For j = 0 To n - 1: cost(i, j) = costRng.Cells(i + 1, j + 1).Value: Next
    Next i
    
    Dim totalCost As Double: totalCost = 0
    Do While i < m + n
        ' 找最低成本位置 (排除已滿足行列)
        Dim minCost As Double: minCost = 1E+30
        Dim minI As Integer, minJ As Integer
        For i = 0 To m - 1
            If supply(i) > 0 Then
                For j = 0 To n - 1
                    If demand(j) > 0 And cost(i, j) < minCost Then
                        minCost = cost(i, j): minI = i: minJ = j
                    End If
                Next j
            End If
        Next i
        
        If minCost = 1E+30 Then Exit Do
        Dim amount As Double: amount = WorksheetFunction.Min(supply(minI), demand(minJ))
        allocation(minI, minJ) = amount
        totalCost = totalCost + amount * minCost
        supply(minI) = supply(minI) - amount
        demand(minJ) = demand(minJ) - amount
    Loop
    
    ' 輸出
    ws.Range("G1").Value = "最小成本法": ws.Range("H1").Value = "總成本": ws.Range("I1").Value = totalCost
    
    For i = 0 To m - 1
        For j = 0 To n - 1: ws.Cells(i + 2, 7 + j).Value = allocation(i, j): Next
    Next i
    
    MsgBox "最小成本法完成!總成本: " & Format(totalCost, "#,##0") '[web:42]
End Sub


VBA 使用操作步驟:
準備工作:
開啟 EXCEL 並建立資料表
準備運輸表:成本矩陣放在 B2:D4(以此例為 3×3)
供給量放在 E2:E4(對應三個供應地)
需求量放在 B5:D5(對應三個需求地)
確認總供給 = 總需求(平衡問題)
進入 VBA 編輯環境
按 Alt + F11 開啟 VBA 編輯器
在左邊專案視窗中,找到你的工作簿,右鍵點選 → 插入 → 模組
新建模組會出現在右邊編輯區

貼上程式碼
將上方「西北角法」或「最小成本法」的完整程式碼複製
貼到 VBA 編輯器的新模組中
如果使用自己的範圍,記得修改這三行:

Set supplyRange = ws.Range("E2:E4")    ' 改成你的供給範圍
Set demandRange = ws.Range("B5:D5")    ' 改成你的需求範圍
Set costRange = ws.Range("B2:D4")      ' 改成你的成本矩陣範圍

執行程式
方法一:在編輯器中執行
點選程式碼任意位置
按 F5 或點選功能表「執行」→「執行副程式」
選擇要執行的副程式(如 NorthwestCornerMethod)

方法二:從 EXCEL 執行
關閉 VBA 編輯器(Alt + F11)
在 EXCEL 功能表:「開發人員」→「巨集」
選擇副程式名稱(如 NorthwestCornerMethod)→「執行」
若沒看到「開發人員」標籤,需先在「檔案」→「選項」→「自訂功能區」打勾啟用

方法三:建立快速鍵(選擇性)
在 EXCEL「開發人員」→「巨集」
選擇副程式 → 「選項」
在「快速鍵」欄位輸入(如 Ctrl+Shift+N)
日後可直接用快速鍵執行

檢查結果
程式執行完後,會跳出訊息框顯示「計算完成!總成本:XXXX」
點「確定」後,回到工作表





P.S 範例引用 全華 管理數學(第八版)(附範例光碟) 王妙伶 9789865037697,好書一本多多使用



沒有留言:

張貼留言

職場毒癌:證照有沒有用,舉手提問

 小編鄭幾天被晚輩提問,考證照有用嗎? 小編整理三個面向 1.口糧 2.貴族 3.加值 這三個面向,作思考發想: 1.口糧:怎說是口糧呢!!!!!直接切入,這寫在履歷上有亮點?ai能否取代?? 最好例子就是駕照,人人會開車,這算技能;太直白會檔到很多人財路,但回到自我發展與規劃,...