指派授課問題
現有A、B、C、D四門課程,需由甲、乙、丙、丁四人講授,並且規定:
每人只講且必須講1門課;每門課必須且只需1人講。
四人分別講每門課的費用示於表中:
課 費用 人 |
A |
B |
C |
D |
甲 |
2 |
10 |
9 |
7 |
乙 |
15 |
4 |
14 |
8 |
丙 |
13 |
14 |
16 |
11 |
丁 |
4 |
15 |
13 |
9 |
帶包python代碼:
from scipy.optimize import linear_sum_assignment import numpy as np #cost =np.array([[4,1,3],[2,0,5],[3,2,2]]) cost =np.array([ [2,10,9,7], [15,4,14,8], [13,14,16,11], [4,15,13,9]]) row_ind,col_ind=linear_sum_assignment(cost) print(row_ind)#開銷矩陣對應的行索引 print(col_ind)#對應行索引的最優指派的列索引 print(cost[row_ind,col_ind])#提取每個行索引的最優指派列索引所在的元素,形成數組 print(cost[row_ind,col_ind].sum())#數組求和 #輸出指派矩陣 p = np.zeros((4,4)) p[row_ind,col_ind]=1 print(p)
暴力python代碼:
# -*- coding: utf-8 -*- import numpy as np import copy c=[2,10,9,7, 15,4,14,8, 13,14,16,11, 4,15,13 ,9 ] c = np.array(c) c = c.reshape((4,4)) all_p=[] class obj: def _init_(self): self.p=[] self.cost=0 for i in range(4): for j in range(4): if j==i: continue for u in range(4): if u==i or u==j : continue for v in range(4): if v==i or v==j or v==u: continue p = np.zeros((4,4)) p[0,i]=p[1,j]=p[2,u]=p[3,v]=1 ans = obj() ans.p = copy.deepcopy(p) ans.cost = sum(sum(c*ans.p)) all_p.append(ans) all_p.sort(key=lambda ans: ans.cost, reverse=False) print(all_p[0].p) print(all_p[0].cost)
我寫的matlab:
clear C=[2 10 9 7 15 4 14 8 13 14 16 11 4 15 13 9]; A = perms(1:4);%perm顯示1,2,3,4四個數的全排列 L = length(A) best=999 best_mat=[] for i=1:L a = zeros(4,4); b = A(i,:);%遍歷全排列中的每一種 c = 1:4; a(sub2ind(size(a), b, c))=1;%a矩陣指定的位置賦值為1 s = sum(sum(a.*C));%求出費用和 if best>s %挑出最大的 best_mat=a; best=s; end end best_mat best
老師的matlab代碼1:
clear n=4; A=perms(1:n); G=size(A); %24 4 size(A,1) 24 size(A,2) 24 n0=G(1); %24 B=[2,10,9,7;15,4,14,8;13,14,16,11;4,15,13,9]; for n1=1:n0 %C為第n1中排列情況下,費用的4個取值 C(1)=B(1,A(n1,1));C(2)=B(2,A(n1,2)); C(3)=B(3,A(n1,3));C(4)=B(4,A(n1,4)); %D{n1}表示第n1種情況下的4個取值 D{n1}=[C(1),C(2),C(3),C(4)]; s(n1)=sum(D{n1}); end %找到最小的,返回a為行左邊,b為縱坐標,a=1,b=9 [a,b]=find(s==min(s)); K=A(b,:)
根據老師的代碼改進我的代碼:
clear C=[2 10 9 7 15 4 14 8 13 14 16 11 4 15 13 9]; A = perms(1:4);%perm顯示1,2,3,4四個數的全排列 L = length(A) for i=1:L a = zeros(4,4); b = A(i,:);%遍歷全排列中的每一種 c = 1:4; a(sub2ind(size(a), b, c))=1;%a矩陣指定的位置賦值為1 D{i}=a; S(i)=sum(sum(a.*C));%求出費用和 end [a,b]=find(S==min(S)) D{b} S(b)
老師的matlab代碼2:隨機生成,不是很好,看運氣
clear A=[2 15 13 4];B=[10 4 14 15];C=[9 14 16 13];D=[7 8 11 9]; Y=zeros(1,1000);s=64;x=zeros(1,4); for i= 1:1000 X=randperm(4); Y(i)=A(X(1))+B(X(2))+C(X(3))+D(X(4)); if Y(i)<s s=Y(i); x=X; end end s,x
網上常見的matlab代碼:
%適用於任意n階系數矩陣 clear all; C=[2 10 9 7, 15 4 14 8, 13 14 16 11, 4 15 13 9, ];%效率矩陣C n=size(C,1);%計算C的行列數n C=C(:);%計算目標函數系數,將矩陣C按列排成一個列向量即可。 A=[];B=[];%沒有不等式約束 Ae=zeros(2*n,n^2);%計算等約束的系數矩陣a for i=1:n for j=(i-1)*n+1:n*i Ae(i,j)=1; end for k=i:n:n^2 Ae(n+i,k)=1; end end Be=ones(2*n,1);%等式約束右端項b Xm=zeros(n^2,1);%決策變量下界Xm XM=ones(n^2,1);%決策變量上界XM [x,z]=linprog(C,A,B,Ae,Be,Xm,XM);%使用linprog求解 x=reshape(x,n,n);%將列向量x按列排成一個n階方陣 disp('最優解矩陣為:');%輸出指派方案和最優值 Assignment=round(x)%使用round進行四舍五入取整 disp('最優解為:'); z
線性規划matlab代碼:
%線性規划 c=[2,10,9,7,15,4,14,8,13,14,16,11,4,15,13,9]; Aeq=[1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0; 0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0; 0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0; 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1; 1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0; 0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0; 0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0; 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1]; beq=[1,1,1,1,1,1,1,1]; lb=zeros(16,1); ub=ones(16,1); [x,fval] = linprog(c,[],[],Aeq,beq,lb,ub)