`

指派问题的匈牙利算法

阅读更多

      昨天帮一个同学完成了他的毕业论文上的指派问题的匈牙利算法程序。以前他们跟我讲那算法的时候,他们就没讲清楚。现在回想起来他们说的匈牙利算法都是不完全正确的。因此以前我就在网上随便帮他们找了一个程序,可是发现那程序25行矩阵就会出问题,运行相当长时间,因为那不是用匈牙利算法解决的。

      他们现在被老师逼了,一定要把结果弄出来,没办法了,我也只好认真看了一下匈牙利算法原理。最后选择了Excel的后台VBA 程序来解决。通过一天的努力,这个匈牙利算法已经弄出来了。下面就给出全部的代码。

'=========================================
'作者:大漠.jxzhoumin
'=========================================

Option Base 1
Public r As Integer
Public row_gou() As Integer
Public col_gou() As Integer
Public gou_min_num As Double
'=================================================
Public Function tj(lb) As Integer
     Dim k As Integer
     k = 2
     Do
         Set myR = Sheets(lb).Cells(k, 1)
         If Trim(myR.Value) = "" Then     '出现空记录
            Exit Do
         End If
         k = k + 1
     Loop Until False
     tj = k - 1
End Function
'================================================
Private Sub CommandButton1_Click()
Application.ScreenUpdating = False
    Call findmin
Application.ScreenUpdating = True
Worksheets("sheet1").Activate
End Sub
Sub findmin()
Dim num As Double, min_num As Double
r = tj("原始数据")
Call copy_data
With Worksheets("sheet1")
For i = 2 To r
   num = 1000
   For j = 2 To r
       If .Cells(i, j).Value < num Then
            min_num = .Cells(i, j).Value
            num = min_num '获得该行的最小数
       End If
   Next j
   For j = 2 To r
       .Cells(i, j).Value = .Cells(i, j).Value - min_num '将每行减该行最小数
   Next j
Next i
'======================================================================================
For i = 2 To r
   num = 1000
   For j = 2 To r
        If .Cells(j, i).Value < num Then
            min_num = .Cells(j, i).Value
            num = min_num '获得该列的最小数
       End If
   Next j
   For j = 2 To r
       .Cells(j, i).Value = .Cells(j, i).Value - min_num '将每列减该列最小数
   Next j
Next i
End With
Call find_draw_zero
End Sub
Function find_draw_zero()
Dim zero_row As Integer
zero_row = 0
zero_row = findzero()
While zero_row > 0
    Call draw_zero(zero_row)
    zero_row = findzero()
Wend
Call bestvalue
End Function
Function findzero() As Integer
Dim zero_num As Integer, zero_row, zero_col As Integer, min_num As Integer
zero_num = 0 '行,列0元素的个数
min_num = 1000
zero_row = 0
zero_col = 0
With Worksheets("sheet1")
For i = 2 To r
    zero_num = 0
    For j = 2 To r
        If .Cells(i, j).Value = 0 Then
            zero_num = zero_num + 1
        End If
    Next j
    If zero_num <> 0 And zero_num < min_num Then
        min_num = zero_num
        zero_row = i
    End If
Next i
End With
If min_num = 1000 Then
   zero_row = 0
End If
findzero = zero_row
End Function
Sub draw_zero(zero_row As Integer)
Dim zero_col As Integer, i As Integer
zero_col = find_col_num(zero_row)
With Worksheets("sheet1")
    .Cells(zero_row, zero_col).Value = "@" '将对应的0划成@
    For i = 2 To r
         If .Cells(zero_row, i).Value = 0 Then
             .Cells(zero_row, i).Value = "*"  '找到对应的行的0划成*
         End If
    Next i
    For i = 2 To r
         If .Cells(i, zero_col).Value = 0 Then
             .Cells(i, zero_col).Value = "*"  '找到对应的列的0划成*
         End If
    Next i
End With
End Sub
Function find_col_num(zero_row As Integer) As Integer
Dim count As Integer, col_num As Integer, min_count As Integer
min_count = 1000
With Worksheets("sheet1")
     For i = 2 To r
         If .Cells(zero_row, i).Value = 0 Then
             count = 0
             For j = 2 To r
                If .Cells(j, i).Value = 0 Or .Cells(j, i).Value = "*" Then
                    count = count + 1
                End If
             Next j
             If count < min_count Then
                 min_count = count
                 find_col_num = i '找到需要标记的0列的数值,该0的列的0的个数最少
             End If
         End If
     Next i
End With
End Function
Function bestvalue() As Boolean
Dim count As Integer
count = 0
With Worksheets("sheet1")
For i = 2 To r
    For j = 2 To r
         If .Cells(i, j).Value = "@" Then
             count = count + 1
         End If
    Next j
Next i
End With
If count = r - 1 Then
   bestvalue = True
   Call show_infor
   MsgBox "达到最优解!"
Else
   bestvalue = False
   Call draw_gou
   Call find_gou_min_num
   Call row_gou_jian
   Call col_gou_jia
   Call init_second
End If
End Function
Sub draw_gou()
Dim i As Integer, count As Integer
Dim row_num, col_num As Integer
i = 1
Erase row_gou
Erase col_gou
ReDim row_gou(1)
ReDim col_gou(1)
With Worksheets("sheet1")
For i = 2 To r
    count = 0
    For j = 2 To r
        If .Cells(i, j).Value = "@" Then
            count = count + 1
        End If
    Next j
    If count = 0 Then
       row_num = i
       If row_gou(0) = 0 Then
           row_u = 0
       Else
           row_u = UBound(row_gou)
       End If
       If col_gou(0) = 0 Then
           col_u = 0
       Else
           col_u = UBound(col_gou)
       End If
       
       For j = 2 To r
           If .Cells(row_num, j).Value = "*" Then
              col_num = j
           End If
       Next j
           
        If chongfu_row(row_num) Then
             ReDim Preserve row_gou(row_u + 1)
             row_gou(row_u + 1) = row_num  '将行画钩的序列值做标记
         End If
         If chongfu_col(col_num) Then
             ReDim Preserve col_gou(col_u + 1)
             col_gou(col_u + 1) = col_num  '将列画钩的序列值做标记
             Call col_to_row(col_num)
         End If
    End If
Next i
End With
End Sub
Function chongfu_row(ByVal row_num As Integer) As Boolean
row_u = UBound(row_gou)
chongfu_row = True
For i = 1 To row_u
    If row_gou(i) = row_num Then
        chongfu_row = False
    End If
Next i
End Function
Function chongfu_col(ByVal col_num As Integer) As Boolean
col_u = UBound(col_gou)
chongfu_col = True
For i = 1 To col_u
    If col_gou(i) = col_num Then
        chongfu_col = False
    End If
Next i
End Function
Sub col_to_row(ByVal col_num As Integer)
row_u = UBound(row_gou)
col_u = UBound(col_gou)
row_num = 0
With Worksheets("sheet1")
For i = 2 To r
    If .Cells(i, col_num).Value = "@" Then
         row_num = i
         If chongfu_row(row_num) Then
             ReDim Preserve row_gou(row_u + 1)
             row_gou(row_u + 1) = row_num  '将行画钩的序列值做标记
         End If
    For j = 2 To r
        If .Cells(row_num, i).Value = "*" Then
            If chongfu_col(col_num) Then
                 ReDim Preserve col_gou(col_u + 1)
                 col_gou(col_u + 1) = i '将列画钩的序列值做标记
                 'Call col_to_row(i) '全套循环函数得出画钩的行
             End If
         End If
    Next j
    End If
Next i
End With
End Sub
Sub find_gou_min_num()
Dim row_u As Integer, row_num As Integer, min_num As Double
min_num = 1000
row_u = UBound(row_gou)
With Worksheets("sheet1")
For i = 1 To row_u
    For j = 2 To r
         row_num = row_gou(i)
         If .Cells(row_num, j).Value <> "*" And .Cells(row_num, j).Value <> "@" Then
             If .Cells(row_num, j).Value < min_num Then
                 min_num = .Cells(row_num, j).Value
                 gou_min_num = min_num
              End If
         End If
    Next j
Next i
End With
End Sub
Sub row_gou_jian()
Dim row_u As Integer, row_num As Integer
row_u = UBound(row_gou)
With Worksheets("sheet1")
For i = 1 To row_u
    For j = 2 To r
         row_num = row_gou(i)
         If .Cells(row_num, j).Value <> "*" And .Cells(row_num, j).Value <> "@" Then
            .Cells(row_num, j).Value = .Cells(row_num, j) - gou_min_num '将画钩的行的数减去最小数
         End If
    Next j
Next i
End With
End Sub
Sub col_gou_jia()
Dim col_u As Integer, col_num As Integer
col_u = UBound(col_gou)
With Worksheets("sheet1")
For i = 1 To col_u
    col_num = col_gou(i)
    For j = 2 To r
         If .Cells(j, col_num).Value <> "*" And .Cells(j, col_num).Value <> "@" Then
            .Cells(j, col_num).Value = Val(Trim(.Cells(j, col_num).Value)) + gou_min_num '将画钩的行的数减去最小数
         End If
    Next j
Next i
End With
End Sub
Sub init_second()
With Worksheets("sheet1")
     For i = 2 To r
         For j = 2 To r
             If .Cells(i, j).Value = "@" Or .Cells(i, j).Value = "*" Then
                .Cells(i, j).Value = 0
             End If
         Next j
     Next i
End With
Call find_draw_zero
End Sub
Sub show_infor()
With Worksheets("sheet1")
For i = 2 To r
    For j = 2 To r
        If .Cells(i, j).Value = "@" Then
            .Cells(i, j).Value = 1
        Else: .Cells(i, j).Value = 0
        End If
    Next j
Next i
End With
End Sub
Sub copy_data()
For i = 1 To r
    For j = 1 To r
        With Worksheets("原始数据")
            num = .Cells(i, j).Value
        End With
        With Worksheets("sheet1")
            .Cells(i, j).Value = num
        End With
    Next j
Next i
End Sub

 

分享到:
评论
1 楼 kimcherwoo 2009-01-04  
有java版本吗?

相关推荐

    指派问题matlab匈牙利算法

    matlab匈牙利算法求解指派问题

    匈牙利算法指派问题matlab代码

    ### 匈牙利算法在指派问题中的应用与MATLAB实现 #### 一、匈牙利算法概述 匈牙利算法是一种高效的解决指派问题的方法,特别适用于成本矩阵(或效率矩阵)的情况,即需要将一系列任务分配给一系列执行者,并使得总...

    指派问题 匈牙利算法实现

    若能在系数矩阵(bij)中找出n个独立的0元素;则令解矩阵(xij)中对应这n个独立的0元素取值为1,其它元素取值为0。将其代入目标函数中得到zk=0,...这就是以(bij)为系数矩阵的指派问题的最优解。也就得到了问题的最优解。

    匈牙利算法在企业员工指派问题的应用.doc

    匈牙利算法在企业员工指派问题的应用 匈牙利算法是一种经典的指派问题解决方法,在企业员工指派问题中扮演着非常重要的角色。该算法可以高效地解决企业员工指派问题,从而提高企业的竞争力。 在企业员工指派问题中...

    基于匈牙利算法的指派问题优化分析PPT课件.pptx

    基于匈牙利算法的指派问题优化分析 在运筹学和管理科学中,指派问题是一个经典的问题,即如何将不同的任务或项目分配给不同的个人或团队以达到最优的效益。匈牙利算法是一种常用的解决指派问题的方法,本文将对其...

    hungary_代码_matlab_匈牙利算法_指派问题_

    匈牙利算法是一种用于解决指派问题的有效方法,它源于图论中的匹配理论。指派问题是一个经典的优化问题,目标是在一组任务与一组执行者之间建立一对一的匹配,使得总成本(或工作量、时间等)达到最小。在这个场景中...

    匈牙利算法C++的程序

    通过上述步骤和技巧,你可以实现一个功能完善的匈牙利算法C++程序,解决实际的指派问题。对于复杂的问题,可以考虑优化搜索策略,例如引入启发式规则来减少搜索空间。同时,理解和掌握匈牙利算法的基本原理,有助于...

    MATLAB源码集锦-基于匈牙利算法的指派问题优化分析

    《MATLAB源码集锦-基于匈牙利算法的指派问题优化分析》是一份针对计算机科学和工程领域的资源,特别关注使用MATLAB语言解决实际的优化问题。在这个压缩包中,重点是匈牙利算法在处理指派问题时的应用。下面我们将...

    基于匈牙利算法的指派问题优化分析.zip

    《基于匈牙利算法的指派问题优化分析》 在计算机科学和运筹学领域,指派问题是一个经典的组合优化问题,它涉及到如何将n个任务有效地分配给n个工作者,使得每个工作者只能承担一个任务,并且每个任务只能由一个工作...

    hungary_代码_matlab_匈牙利算法_指派问题_源码.zip

    标题中的“hungary_代码_matlab_匈牙利算法_指派问题_源码”表明这是一个关于使用MATLAB实现匈牙利算法解决指派问题的源代码集合。匈牙利算法,也称为Kuhn-Munkres算法,是解决完全匹配问题的一种高效方法,尤其适用...

    fp.zip_Hungarian_hungarian algorithm_匈牙利算法_指派问题_指派问题的匈牙利算法

    总之,匈牙利算法是解决指派问题的一种重要方法,广泛应用于生产计划、调度优化、网络路由等多种实际场景。通过理解并掌握匈牙利算法的原理和实现,我们可以有效地解决这些优化问题,提高工作效率。

    assign_matlab里的assig_matlabassign_全局指派_匈牙利算法_

    在MATLAB编程环境中,"assign_matlabassign_全局指派_匈牙利算法"涉及到的是一个优化问题的解决方法,特别是用于处理任务分配或资源匹配的问题。这篇文章将深入探讨匈牙利算法在MATLAB中的实现,以及其在全局指派...

    匈牙利算法的C++语言代码

    匈牙利算法是一种用于解决二分图最大匹配问题的有效算法,由Kuhn在1955年首次提出,后来由Munkres进一步发展和完善。在计算机科学中,尤其是在图论和算法设计领域,匈牙利算法有着广泛的应用,如任务分配、资源调度...

    matlab程序匈牙利算法指派问题.zip

    标题中的“matlab程序匈牙利算法指派问题”揭示了我们要探讨的核心主题:匈牙利算法在MATLAB环境中的实现。匈牙利算法,又称Kuhn-Munkres算法,是一种用于解决指派问题的有效方法。指派问题是一个经典的线性优化问题...

    匈牙利算法用C语言描述

    匈牙利算法是一种用于解决匹配问题的图论算法,它主要应用于解决二分图的最大匹配问题。二分图是图中的一种特殊类型,其节点可以分为两个不相交的集合,所有的边都连接不同集合中的节点。匈牙利算法的核心在于通过...

    求解指派问题的JV算法

    相较于经典的Kuhn-Munkres(KM,也称为匈牙利)算法,JV算法在特定情况下能提供更快的求解速度,尤其是在大规模问题中,它能减少计算复杂度,通常比KM算法快n倍。 JV算法的核心思想是通过一系列迭代步骤逐步改进...

Global site tag (gtag.js) - Google Analytics