匈牙利算法python实现,初学版= =

1、问题描述
问题描述:N个人分配N项任务,一个人只能分配一项任务,一项任务只能分配给一个人,将一项任务分配给一个人是需要支付报酬,如何分配任务,保证支付的报酬总数最小。

2、算法步骤:
在这里插入图片描述
3、具体算法分析—匈牙利算法

Step1.
在这里插入图片描述
Step2
在这里插入图片描述
Step3.在这里插入图片描述
在这里插入图片描述

Step4.在这里插入图片描述在这里插入图片描述

Step5.在这里插入图片描述

4、python代码

#矩阵输入
def input_s():
    a1=int(input("输入方阵边长:"))
    n=0 #循环计数器,确定何时跳出循环
    while 1:
        b=input("矩阵第{}行:".format(n+1))
        b1=list(map(eval,b.split(",")))  #将字符串改为数值列表
        #检查每一行输入的数是否一样多,即是否为方阵
        if a1!=len(b1):
            print("输入错误")
            b2,a1=input_s()
            break
        #numpy.vstack将输入每一行合成矩阵
        if n==0:
            b2=b1
        else:
            b2=np.vstack((b2,b1))
        n+=1
        if n==len(b1):
            break
    return b2,a1

#第一步,每行每列减去最小数
def step1():
    min_0=[] #存储每行每列最小数的列表
    #每行减去最小数
    for i in range(n):
        for j in range(n):
            if j==0:
                min_0.append(b[i,j])
            else:
                if min_0[i]>b[i,j]:
                    min_0[i]=b[i,j]
        b1[i]=b[i]-min_0[i]    
    #再每列减去最小数
    for i in range(n):
        for j in range(n):
            if j==0:
                min_0[i]=b1[j,i]
            else:
                if min_0[i]>b1[j,i]:
                    min_0[i]=b1[j,i]
        b1[:,i]=b1[:,i]-min_0[i]
    #进入下一步
    step3(b1)
    
#第3步,直线覆盖
def step3(b1):
    b2=np.zeros((n,n))
    b3=b2.copy()
    m=0
    for i in range(n):
        a=0
        a1=0
        for j in range(n):
            if b1[i,j]==0 and b2[i,j]==0:
                a+=1
                a1=j
                
        if a==1:
            b2[:,a1]+=1
            m+=1
            b3[i,a1]+=1
    for i in range(n):
        a=0
        a1=0
        for j in range(n):
            if b1[j,i]==0 and b2[j,i]==0:
                a+=1
                a1=j
        if a==1:
            b2[a1]+=1
            m+=1
            b3[a1,i]+=1
#有未被直线覆盖的0,但是0之间形成回路
    a2=1
    for i in range(n):
        for j in range(n):
            if b2[i,j]==0 and b1[i,j]==0:
                if a2%2==0:
                    continue
                b3[i,j]+=1
                b2[i]+=1
                a2+=1
                m+=1
    #画线数目等于方阵边数,已经找到最优解
    if m==n:
        zuiyoujie(b3)
    elif m<n:
        step4(b2)
    else:
        print("程序错误!")
        exit()

def zuiyoujie(b3):
    Z=0
    for i in range(n):
        for j in range(n):
            if b3[i,j]==1:
                Z=Z+b[i,j]
                a=(i+1,j+1)
                print("原矩阵位置:{}".format(a),end='')
    print("最优解为Z={}".format(Z))    

def step4(b2):
    min_1=0
    for i in range(n):
        for j in range(n):
            if min_1==0 and b2[i,j]==0 :
                min_1=b1[i,j]
            elif b2[i,j]==0 and min_1>b1[i,j]:
                min_1=b1[i,j]
    for i in range(n):
        for j in range(n):
            if b2[i,j]==0:
                b1[i,j]=b1[i,j]-min_1
            elif b2[i,j]==2:
                b1[i,j]+=min_1
    step3(b1)


import numpy as np
print("请输入矩阵,一次性输入一行,逗号分隔:")
b,n=input_s()
b1=b.copy()
step1()


  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值