16、表上作业法

# -*- coding: utf-8 -*-
"""
Created on Fri Mar 15 10:12:59 2019

@author: zhangchaoyu
"""

"""
这里特用来处理供给平衡的运输问题
"""

def value_idex(e):
    return e[-1]

def minimum_element(C, Br, Bc):

    X = [[0 for j in range(len(C[i]))] for i in range(len(C))]
    
    idexs = []
    for i in range(len(C)):
        for j in range(len(C[i])):
            idexs.append([i,j,C[i][j]])
        
    idexs.sort(key = value_idex)
    
    for i in range(len(idexs)):
        row = idexs[i][0]
        col = idexs[i][1]
        row_left = Br[row]
        for k in range(len(X[row])):
            if k != col:
                row_left -= X[row][k]
        col_left = Bc[col]
        for k in range(len(X)):
            if k != row:
                col_left -= X[k][col]
        X[row][col] = min(row_left,col_left)
    
    print("最小元素法:"+ str(sum([sum([C[i][j]*X[i][j] for j in range(len(X[i]))]) for i in range(len(X))])))
    
    return X

def vogel_1(C, Br, Bc):
    
    row_used = []
    col_used = []
    
    X = [[0 for j in range(len(C[i]))] for i in range(len(C))]
    
    while True:
        
        row_can = []
        col_can = []
        for i in range(len(C)):
            if i not in row_used:
                row_can.append(i)
        for i in range(len(C[0])):
            if i not in col_used:
                col_can.append(i)
        
        if len(C) == len(row_used)+1:
            idex_row = row_can[0]
            for i in range(len(col_can)):
                col_left = Bc[col_can[i]]
                for j in range(len(X)):
                    if j != idex_row:
                        col_left -= X[j][col_can[i]]
                X[idex_row][col_can[i]] = col_left
            break
        
        if len(C[0]) == len(col_used)+1:
            idex_col = col_can[0]
            for i in range(len(row_can)):
                row_left = Br[row_can[i]]
                for j in range(len(X[0])):
                    if j != idex_col:
                        row_left -= X[row_can[i]][j]
                X[row_can[i]][idex_col] = row_left
            break
        
        Dr = []
        Dc = []
        
        for i in range(len(row_can)):
            first = min(C[row_can[i]][col_can[0]],C[row_can[i]][col_can[1]])
            second = max(C[row_can[i]][col_can[0]],C[row_can[i]][col_can[1]]) 
            for j in range(2,len(col_can)):
                if second > C[row_can[i]][col_can[j]]:
                    second = C[row_can[i]][col_can[j]]
                    first,second = min(first,second),max(first,second)    
            Dr.append(second-first)
            
        for i in range(len(col_can)):
            first = min(C[row_can[0]][col_can[i]],C[row_can[1]][col_can[i]])
            second = max(C[row_can[0]][col_can[i]],C[row_can[1]][col_can[i]]) 
            for j in range(2,len(row_can)):
                if second > C[row_can[j]][col_can[i]]:
                    second = C[row_can[j]][col_can[i]]
                    first,second = min(first,second),max(first,second)   
            Dc.append(second-first)
            
        row_max = Dr[0]
        row_idex_max = row_can[0]
        for i in range(1,len(Dr)):
            if row_max < Dr[i]:
                row_max = Dr[i]
                row_idex_max = row_can[i]
        
        col_max = Dc[0]
        col_idex_max = col_can[0]
        for i in range(1,len(Dc)):
            if col_max < Dc[i]:
                col_max = Dc[i]
                col_idex_max = col_can[i]
        
        if col_max > row_max:
            idex_row = row_can[0]
            for i in range(1,len(row_can)):
                if C[idex_row][col_idex_max] > C[row_can[i]][col_idex_max]:
                    idex_row = row_can[i]
            
            row_left = Br[idex_row]
            for i in range(len(X[idex_row])):
                if i != col_idex_max:
                    row_left -= X[idex_row][i]
            col_left = Bc[col_idex_max]
            for i in range(len(X)):
                if i != idex_row:
                    col_left -= X[i][col_idex_max]
            if row_left <= col_left:
                X[idex_row][col_idex_max] = row_left
                row_used.append(idex_row)
            else:
                X[idex_row][col_idex_max] = col_left
                col_used.append(col_idex_max)
        else:
            idex_col = col_can[0]
            for i in range(1,len(col_can)):
                if C[row_idex_max][idex_col] > C[row_idex_max][col_can[i]]:
                    idex_col = col_can[i]
            row_left = Br[row_idex_max]
            for i in range(len(X[row_idex_max])):
                if i != idex_col:
                    row_left -= X[row_idex_max][i]
            col_left = Bc[idex_col]
            for i in range(len(X)):
                if i != row_idex_max:
                    col_left -= X[i][idex_col]
            if row_left <= col_left:
                X[row_idex_max][idex_col] = row_left
                row_used.append(row_idex_max)
            else:
                X[row_idex_max][idex_col] = col_left
                col_used.append(idex_col)
            
        print(X)
    print(X)
    print("vogel法:"+ str(sum([sum([C[i][j]*X[i][j] for j in range(len(X[i]))]) for i in range(len(X))])))           
    return X


def vogel_2(C, Br, Bc):
    
    idexs = []
    for i in range(len(C)):
        for j in range(len(C[i])):
            dis_row = -1
            for k in range(len(C[i])):
                if C[i][k] - C[i][j] >= 0 and k != j:
                    if dis_row == -1:
                        dis_row = C[i][k] - C[i][j]
                    elif dis_row > C[i][k] - C[i][j]:
                        dis_row = C[i][k] - C[i][j]
            dis_col = -1
            for k in range(len(C)):
                if C[k][j] - C[i][j] >= 0 and k != i:
                    if dis_col == -1:
                        dis_col = C[k][j] - C[i][j]
                    elif dis_col > C[k][j] - C[i][j]:
                        dis_col = C[k][j] - C[i][j]
                        
            if dis_row >= dis_col:
                flag = 1
            else:
                flag = 2
            idexs.append([i,j,C[i][j],flag,max(dis_row,dis_col)])
    
    idexs.sort(key = value_idex, reverse = True)
    X = [[0 for j in range(len(C[i]))] for i in range(len(C))]
    
    for i in range(len(idexs)):
        row = idexs[i][0]
        col = idexs[i][1]
        row_left = Br[row]
        for k in range(len(X[row])):
            if k != col:
                row_left -= X[row][k]
        col_left = Bc[col]
        for k in range(len(X)):
            if k != row:
                col_left -= X[k][col]
        X[row][col] = min(row_left,col_left)
    
    print("最小元素法:"+ str(sum([sum([C[i][j]*X[i][j] for j in range(len(X[i]))]) for i in range(len(X))])))
    
    return X

def examples_test(examples, test):
    result1 = []
    result2 = []
    for i in range(len(examples)):
        C = examples[i][0]
        Br = examples[i][1]
        Bc = examples[i][2]
        X1 = minimum_element(C, Br, Bc)
        result1.append(sum([sum([C[i][j]*X1[i][j] for j in range(len(X1[i]))]) for i in range(len(X1))]))
        X2 = vogel_1(C, Br, Bc)
        result2.append(sum([sum([C[i][j]*X2[i][j] for j in range(len(X1[i]))]) for i in range(len(X2))]))
    for i in range(len(result1)):
        print(str(result1[i]) + "   " + str(result2[i]) + "   " + str(test[i]))

examples = []
examples.append([[[3,11,3,10],[1,9,2,8],[7,4,10,5]],[7,4,9],[3,6,5,6]])
examples.append([[[10.8,1e10,1e10,1e10],[10.8,11.1,1e10,1e10],[10.8,11.1,11,1e10],[10.8,11.1,11,11.3],[10.8,11.1,11,11.3]],[10,15,25,20,30],[25,35,30,10]])
examples.append([[[10.8,1e10,1e10,1e10],[10.95,11.1,1e10,1e10],[11.1,11.25,11,1e10],[11.25,11.4,11.15,11.3],[10.8,11.1,11,11.3]],[10,15,25,20,30],[25,35,30,10]])
examples.append([[[2,3,5],[14,13,17],[7,8,3]],[2,2,1],[1,1,3]])
examples.append([[[2,15,13,4],[10,4,14,15],[9,14,16,13],[7,8,11,9]],[1,1,1,1],[1,1,1,1]])

test = [85, 1101.5, 1103.75, 40, 28]
#检验所有例子和结果
examples_test(examples, test)

C = examples[-1][0]
Br = examples[-1][1]
Bc = examples[-1][2]

X0 = minimum_element(C, Br, Bc)
X1= vogel_1(C, Br, Bc)

 

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值