狠狠撸

狠狠撸Share a Scribd company logo
1 题目
  某厂生产一种弹子锁具,每个锁具有n个槽,每个槽有m个高度,每个槽的高
度从{1,2,…,m}这m个数(单位略)中任取一个,限制至少有一个相邻的槽
高之差等于m-1,且至少有3个不同的槽高。每个槽的高度取遍这m个数且满足上
面这两个限制时生产出一批锁。
  对于同一批中两个锁具是否能够互开,有以下试验结果:若二者相对应的 n
个槽的高度中有 n-1 个相同,另一个槽的高度差为 1,则能互开,在其它情形下
不可能互开。将这一批锁按槽高数之和分为奇数(A)和偶数(B)两类。请给出这
两类锁之间的最大匹配。


2 分析
 1. 求出所有满足条件的锁,和为奇数的保存在矩阵 LMA 中,          和为偶数的保存
    在矩阵 LMB 中,这样我们便得到了锁与自然数的映射(矩阵行标)。
 2. 建立邻接矩阵,若可以互开则设置相应位置为 1 否则设为 0.
 3. 利用 Edmonds 算法求完美匹配。
    ? 两个数组记录匹配,设 MatA,MatB。例如 MatA(i)=j 表示 A 中第 i 个
      元素与 B 中的第 j 个元素相匹配(此时必须有 MatB(j)=i)    。
    ? 三个数组 XYZ 用来求某个未匹配点的增广轨。
    ? 具体过程有:
      a) 初始化 MatA,MatB,X,Y,Z 为 0;
      b) 若 MatA 中不存在 0 元素,则表明匹配已经是最大匹配,算法结束。
         若 A 中存在未匹配点,任取一未匹配点 i。
      c) 将 i 所有相邻结点在 Y 中标记为 i。
      d) 若 Y 与 Z 相同,表明 i 没有与之相应的匹配,将 MatA(i)标记为-1,
         转至 b。否则设 Y-Z 中第一个元素的下标为 j。若 j 不在匹配中,
         则得到一个增广轨 P,从 j 开始逆向得到一条边在匹配和非匹配
         中交替出现的路径,取匹配为原匹配与该增广轨的对称差,转至
         b。
      e) 若 j 在匹配中,则标记 Z(j)=Y(j)。假设 MatB(j)=i(即与 j 相匹
         配的元素为 i),记 X(i)=j,并转至 c。
      f) 清空 XYZ,转至 b。


3 实现
  Edmonds 算法(匈牙利算法)的关键在于寻找增广轨并求原匹配与该增广轨
的对称差,下面结合代码详细说明增广轨的求法:
1. 首先寻找初始匹配,为方便起见可以选取 A 中第一个元素,代码实现:
     j = find(AB(1,:), 1);
     MatA(1)=j; MatB(j)=1;


2. 接着只要 MatA 中存在 0 元素就表明 A 中存在尚未匹配点(不能匹配的点用-1
表示) ,  为方便起见可以选取第一个 0 元素(设下标为 i)为下次进行匹配的
点,代码如下:
     while length(find(MatA==0)) ~= 0      % 存在不匹配的元素
       J = find(MatA==0); i = J(1);      % 第 i 个元素未被匹配
       init = i;


3. 标记 X(i)=0 (标记为 0 方便逆向寻找增广轨,可以做为终结条件),并标记
Y 中所有    与 i 相邻的结点为 i,代码如下:
     X(i)=0;
     J = find(AB(i,:));                 % J 为所有与 i 相邻结点
     Y(J) = i; j=J(1);


4. 当 Y=Z 时表明不存在 i 的匹配,此时清空 XYZ 并标记 MatA(i)=-1 继续下次尚
未匹配点的 匹配,   否则当 j 在匹配中时, 标记 Z(j)=Y(j),设与 j 匹配的点为 i,
标记 Y 中所有 I 相邻的结点,并记 Y-Z 中第一个元素的下标为 j。代码如下:
     if MatB(j) ~= 0                 % j 是匹配点
        Z(j) = Y(j);
        i = MatB(j);
        X(i)=j;
        J = find(AB(i,:));
        Y(J)=i;
        J = find(Y);
        JJ = find(Z);
        J = setxor(intersect(J, JJ), J);
        j=J(1);

5. 如果 j 不在匹配中,则表明已经找到了一个增广轨,接下来就是要用原匹配
与增广轨的 对称差来替代原来的匹配,   例如最后一次 i=8, 时发现 MatB(8)=0
                                 j=8
(即 8 不在匹配中) ,之后便可以利用 X 和 Z 中的数据来得到一条增广轨:

      下标       1      2      3     4    5    6    7   8
      X        0                        3B   1B       6B
      Y                                               NM
      Z        1A            6A              5A
得到增广轨后便更新原来匹配,其具体代码实现:
            i = Y(j);
            MatA(i) = j;
            MatB(j) = i;
            while X(i)
                j = X(i);
                i = Z(j);
                MatA(i) = j;
                MatB(j) = i;
            end
            break;


6. 最后为方便人机交互,可以用 Matlab GUI 设计简单的界面。
function pushbutton1_Callback(hObject, eventdata, handles)
a = get(handles.edit1, 'String');
b = get(handles.edit2, 'String');
str = Edmonds(str2num(a), str2num(b));
set(handles.edit4, 'String', str);
guidata(hObject, handles);




4 结果
                               槽数
                                          4         5
                         高度
                                 4       32       180
                                 5       50       378
锁具装箱
5 改进
  从结果中可以看到当有 5 个槽 5 个高度时匹配有 378 个,此时建立邻接矩阵
为大于 378*378 的矩阵,随着槽数和高度的增加,该程序对内存空间的要求会很
高,而矩阵中真正有用的标记并不多,故空间利用率是很低的,但此方法的优点
在于可以充分利用 Matlab 的内建函数,思路清晰代码简洁。一种改进方法是不
用邻接矩阵,   令每个结点对应一个由其邻接结点构成的向量,这样便可减少空间
需求,同时代码量也会增加,对编程能力要求较高。


6 源码
LockMap.m

function [LMA, LMB] = LockMap(n, m)
% LOCKMAP - 求解满足条件锁并设置相应的映射
% 输入参数:n 表槽数,m 表高度数。
% 输出参数:LMA,LMB 分别为二维矩阵表示自然数到满足条件锁之间的映射。

global jiA ouB ary A B mm N            % 调用递归函数时要用到的变量所以
                                       % 设为全局
N = n; mm = m;
jiA=0; ouB=0;
A=[]; B=[];
ary = zeros(1, n);
RecuCal(n);
LMA=A; LMB=B;
[lena, n] = size(LMA);
[lenb, n] =size(LMB);
if lena>lenb
    temp = LMA; LMA=LMB;LMB=temp;
    temp = lena;lena=lenb;lenb=temp;
end



RecuCal.m

function RecuCal(n)
% RECUCAL - 递归函数
global jiA ouB ary A B mm N
if n ==1
    for k=1:mm
ary(1) = k;
            Max = max(ary); Min = min(ary);
            num = 0; neighbor = 0;
            for i=1:N
                num = num + (Max-ary(i))*(ary(i)-Min);
                if (i~=N)
                     neighbor = max(neighbor, abs(ary(i)-ary(i+1)));
                end
            end
            if (neighbor > mm-1.5)&&(num > 0.5)
                if mod(sum(ary), 2)                % 奇数,属于 A 类
                     jiA = jiA+1;
                     A(jiA,:) = ary;
                else                         % 偶数,属于 B 类
                     ouB = ouB+1;
                     B(ouB,:) = ary;
                end
            end
      end
else
      for k=1:mm
          ary(n) = k;
          RecuCal(n-1);
      end
end



BuildMatrix.m

function AB = BuildMatrix(LMA, LMB)
% BUILDMATRIX - 建立邻接矩阵,若 i 与 j 之间可以互开则 AB(i,j)=1,否则为 0。
AB = [];
[lena, n] = size(LMA);
[lenb, n] =size(LMB);

for i = 1:lena
    for j=1:lenb
        tmp = 0;
        for k=1:n
            tmp = tmp + abs(LMA(i,k)-LMB(j,k));
        end
        if tmp == 1
            AB(i, j)=1;
        end
end
end



Edmonds.m
function str = Edmonds(n, m)
% EDMONDS - Edmonds 算法寻找完美匹配

str = [];
[LMA, LMB] = LockMap(n, m);
AB = BuildMatrix(LMA, LMB);
lena = length(LMA);
lenb = length(LMB);
if lena==0
    disp('其中一个分组为空,         无法匹配'); %当 n=m=3 时只有偶数组无奇数组,不能完成
匹配
    return;
end
MatA = zeros(1, lena);
MatB = zeros(1, lenb);
X = MatA; Y=MatB; Z=Y;
NumNoMat = 0;                       % 无法匹配的点的个数
% 最初匹配,只有一个匹配
j = find(AB(1,:), 1);
MatA(1)=j; MatB(j)=1;

while length(find(MatA==0)) ~= 0         % 存在不匹配的元素
    J = find(MatA==0); i = J(1);         % 第 i 个元素未被匹配
    init = i; X(i)=0;
    J = find(AB(i,:));                   % J 为所有与 i 相邻结点
    Y(J) = i; j=J(1);
    while ~isempty(find(Y~=Z))
        if MatB(j) ~= 0                  % j 是匹配点
             Z(j) = Y(j);
             i = MatB(j);
             X(i)=j;
             J = find(AB(i,:));
             Y(J)=i;
             J = find(Y);
             JJ = find(Z);
             J = setxor(intersect(J, JJ), J);
             j=J(1);
        else                             % j 不是匹配点
             i = Y(j);
MatA(i) = j;
               MatB(j) = i;
               while X(i)
                   j = X(i);
                   i = Z(j);
                   MatA(i) = j;
                   MatB(j) = i;
               end
               break;
         end
    end
    % 如果 Y==Z 则表明该点没有与之相应的匹配,即不存在完美匹配,在 MatA 中标
    % 记为-1。
    if isempty(find(Y~=Z, 1))
        NumNoMat = NumNoMat + 1;
        MatA(init) = -1;
    end
    X(1:lena)=0; Y(1:lenb)=0; Z=Y;
end
total = 0;
for i=1:lena
    k = MatA(i);
    if k<=0 continue; end               % k<=0 时表明匹配不存在
    stra = ''; strb = '';
    for j=1:n
        stra = [stra, num2str(LMA(i, j)), ' '];
        strb = [strb, num2str(LMB(k, j)), ' '];
    end
    str = [str, stra, '------ ', strb, 10];
    total = total + 1;
end
str = [str, '匹配个数有:', num2str(total)];


GUI1.m
function varargout = GUI1(varargin)
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton', gui_Singleton, ...
                   'gui_OpeningFcn', @GUI1_OpeningFcn, ...
                   'gui_OutputFcn', @GUI1_OutputFcn, ...
                   'gui_LayoutFcn', [] , ...
                   'gui_Callback', []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
     [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
     gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT



% --- Executes just before GUI1 is made visible.
function GUI1_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;

guidata(hObject, handles);




function varargout = GUI1_OutputFcn(hObject, eventdata, handles)

varargout{1} = handles.output;



function pushbutton1_Callback(hObject, eventdata, handles)
a = get(handles.edit1, 'String');
b = get(handles.edit2, 'String');
str = Edmonds(str2num(a), str2num(b));
set(handles.edit4, 'String', str);
guidata(hObject, handles);

function edit1_Callback(hObject, eventdata, handles)

input = str2num(get(hObject, 'String'));
guidata(hObject, handles);

function edit1_CreateFcn(hObject, eventdata, handles)

if ispc && isequal(get(hObject,'BackgroundColor'),
get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
function edit2_Callback(hObject, eventdata, handles)

input = str2num(get(hObject, 'String'));
guidata(hObject, handles);

function edit2_CreateFcn(hObject, eventdata, handles)

if ispc && isequal(get(hObject,'BackgroundColor'),
get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function slider1_Callback(hObject, eventdata, handles)




function slider1_CreateFcn(hObject, eventdata, handles)

if isequal(get(hObject,'BackgroundColor'),
get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end




function text_result_Callback(hObject, eventdata, handles)




function text_result_CreateFcn(hObject, eventdata, handles)

if ispc && isequal(get(hObject,'BackgroundColor'),
get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end




function edit4_Callback(hObject, eventdata, handles)




function edit4_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'),
get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function pushbutton2_Callback(hObject, eventdata, handles)

set(handles.edit4, 'String', '');
set(handles.edit1, 'String', '');
set(handles.edit2, 'String', '');

More Related Content

What's hot (19)

支持向量机算法
支持向量机算法支持向量机算法
支持向量机算法
ruxianzaixin
?
07.第七章用惭补迟濒补产解常微分方程
07.第七章用惭补迟濒补产解常微分方程07.第七章用惭补迟濒补产解常微分方程
07.第七章用惭补迟濒补产解常微分方程
Xin Zheng
?
Scilab introduction(Scilab 介紹)
Scilab introduction(Scilab 介紹)Scilab introduction(Scilab 介紹)
Scilab introduction(Scilab 介紹)
JIANG MING-LI
?
A ROBUST MODELING FOR MULTIPLE NONLINEAR REGRESSION USING BEZIER SURFACE
A ROBUST MODELING FOR MULTIPLE NONLINEAR REGRESSION USING BEZIER SURFACE     A ROBUST MODELING FOR MULTIPLE NONLINEAR REGRESSION USING BEZIER SURFACE
A ROBUST MODELING FOR MULTIPLE NONLINEAR REGRESSION USING BEZIER SURFACE
Jian Michael
?
02.第二章用惭补迟濒补产求导
02.第二章用惭补迟濒补产求导02.第二章用惭补迟濒补产求导
02.第二章用惭补迟濒补产求导
Xin Zheng
?
01.第一章用惭补迟濒补产求极限
01.第一章用惭补迟濒补产求极限01.第一章用惭补迟濒补产求极限
01.第一章用惭补迟濒补产求极限
Xin Zheng
?
础肠尘图论
础肠尘图论础肠尘图论
础肠尘图论
also24
?
第2章数据类型、运算符和表达式
第2章数据类型、运算符和表达式第2章数据类型、运算符和表达式
第2章数据类型、运算符和表达式
summerfeng
?
Sicmutils 介紹:Scmutils 的 Clojure 版函式庫
Sicmutils 介紹:Scmutils 的 Clojure 版函式庫Sicmutils 介紹:Scmutils 的 Clojure 版函式庫
Sicmutils 介紹:Scmutils 的 Clojure 版函式庫
睿麒 王
?
惭础罢尝础叠冲曲面作图
惭础罢尝础叠冲曲面作图惭础罢尝础叠冲曲面作图
惭础罢尝础叠冲曲面作图
byron zhao
?
C1 discrete time signals and systems in the time-domain
C1 discrete time signals and systems in the time-domainC1 discrete time signals and systems in the time-domain
C1 discrete time signals and systems in the time-domain
Pei-Che Chang
?
计算机组成原理题
计算机组成原理题计算机组成原理题
计算机组成原理题
Huaijin Chen
?
支持向量机算法
支持向量机算法支持向量机算法
支持向量机算法
ruxianzaixin
?
07.第七章用惭补迟濒补产解常微分方程
07.第七章用惭补迟濒补产解常微分方程07.第七章用惭补迟濒补产解常微分方程
07.第七章用惭补迟濒补产解常微分方程
Xin Zheng
?
Scilab introduction(Scilab 介紹)
Scilab introduction(Scilab 介紹)Scilab introduction(Scilab 介紹)
Scilab introduction(Scilab 介紹)
JIANG MING-LI
?
A ROBUST MODELING FOR MULTIPLE NONLINEAR REGRESSION USING BEZIER SURFACE
A ROBUST MODELING FOR MULTIPLE NONLINEAR REGRESSION USING BEZIER SURFACE     A ROBUST MODELING FOR MULTIPLE NONLINEAR REGRESSION USING BEZIER SURFACE
A ROBUST MODELING FOR MULTIPLE NONLINEAR REGRESSION USING BEZIER SURFACE
Jian Michael
?
02.第二章用惭补迟濒补产求导
02.第二章用惭补迟濒补产求导02.第二章用惭补迟濒补产求导
02.第二章用惭补迟濒补产求导
Xin Zheng
?
01.第一章用惭补迟濒补产求极限
01.第一章用惭补迟濒补产求极限01.第一章用惭补迟濒补产求极限
01.第一章用惭补迟濒补产求极限
Xin Zheng
?
础肠尘图论
础肠尘图论础肠尘图论
础肠尘图论
also24
?
第2章数据类型、运算符和表达式
第2章数据类型、运算符和表达式第2章数据类型、运算符和表达式
第2章数据类型、运算符和表达式
summerfeng
?
Sicmutils 介紹:Scmutils 的 Clojure 版函式庫
Sicmutils 介紹:Scmutils 的 Clojure 版函式庫Sicmutils 介紹:Scmutils 的 Clojure 版函式庫
Sicmutils 介紹:Scmutils 的 Clojure 版函式庫
睿麒 王
?
惭础罢尝础叠冲曲面作图
惭础罢尝础叠冲曲面作图惭础罢尝础叠冲曲面作图
惭础罢尝础叠冲曲面作图
byron zhao
?
C1 discrete time signals and systems in the time-domain
C1 discrete time signals and systems in the time-domainC1 discrete time signals and systems in the time-domain
C1 discrete time signals and systems in the time-domain
Pei-Che Chang
?
计算机组成原理题
计算机组成原理题计算机组成原理题
计算机组成原理题
Huaijin Chen
?

Viewers also liked (7)

Indian partnership act, 1932
Indian partnership act, 1932Indian partnership act, 1932
Indian partnership act, 1932
Manish Kaushik
?
Dear john smith (edited letter)
Dear john smith (edited letter)Dear john smith (edited letter)
Dear john smith (edited letter)
CdnChiguy
?
Lifestyle tips
Lifestyle tipsLifestyle tips
Lifestyle tips
ssacasse
?
B tech cse ffcs curriculum_fb display
B tech cse ffcs curriculum_fb displayB tech cse ffcs curriculum_fb display
B tech cse ffcs curriculum_fb display
anouncia_scse
?
Presentation for internship
Presentation for internshipPresentation for internship
Presentation for internship
visayafan
?
Dividend Policy Report
Dividend Policy ReportDividend Policy Report
Dividend Policy Report
Christine Manongsong
?
Hardware
HardwareHardware
Hardware
harpanda
?
Indian partnership act, 1932
Indian partnership act, 1932Indian partnership act, 1932
Indian partnership act, 1932
Manish Kaushik
?
Dear john smith (edited letter)
Dear john smith (edited letter)Dear john smith (edited letter)
Dear john smith (edited letter)
CdnChiguy
?
Lifestyle tips
Lifestyle tipsLifestyle tips
Lifestyle tips
ssacasse
?
B tech cse ffcs curriculum_fb display
B tech cse ffcs curriculum_fb displayB tech cse ffcs curriculum_fb display
B tech cse ffcs curriculum_fb display
anouncia_scse
?
Presentation for internship
Presentation for internshipPresentation for internship
Presentation for internship
visayafan
?

Similar to 锁具装箱 (20)

Ihome inaction 篇外篇之fp介绍
Ihome inaction 篇外篇之fp介绍Ihome inaction 篇外篇之fp介绍
Ihome inaction 篇外篇之fp介绍
dennis zhuang
?
第1章 Matlab操作基础
第1章  Matlab操作基础第1章  Matlab操作基础
第1章 Matlab操作基础
eterou
?
電路學第七章 交流穩態分析
電路學第七章 交流穩態分析電路學第七章 交流穩態分析
電路學第七章 交流穩態分析
Fu Jen Catholic University
?
对偶分解与拉格朗日松弛在自然语言处理推理的应用导论
对偶分解与拉格朗日松弛在自然语言处理推理的应用导论对偶分解与拉格朗日松弛在自然语言处理推理的应用导论
对偶分解与拉格朗日松弛在自然语言处理推理的应用导论
zhaoweihb
?
【逆转胜】数学学测总复习讲义
【逆转胜】数学学测总复习讲义【逆转胜】数学学测总复习讲义
【逆转胜】数学学测总复习讲义
lungtengtech
?
诲蝉辫肠丑01资料结构资料结构资料结构资料结构资料结构资料结构资料结构资料结构.辫辫迟
诲蝉辫肠丑01资料结构资料结构资料结构资料结构资料结构资料结构资料结构资料结构.辫辫迟诲蝉辫肠丑01资料结构资料结构资料结构资料结构资料结构资料结构资料结构资料结构.辫辫迟
诲蝉辫肠丑01资料结构资料结构资料结构资料结构资料结构资料结构资料结构资料结构.辫辫迟
LinPhil
?
人机对弈编程概述
人机对弈编程概述人机对弈编程概述
人机对弈编程概述
勇浩 赖
?
Ppt 26-50
Ppt 26-50Ppt 26-50
Ppt 26-50
hungchiayang1
?
实验一 Mathematica软件介绍
实验一   Mathematica软件介绍实验一   Mathematica软件介绍
实验一 Mathematica软件介绍
guestfe33f0e
?
实验一 Mathematica软件介绍
实验一   Mathematica软件介绍实验一   Mathematica软件介绍
实验一 Mathematica软件介绍
Xin Zheng
?
Ppt 1-50
Ppt 1-50Ppt 1-50
Ppt 1-50
hungchiayang1
?
第4章 自顶向下的语法分析
第4章 自顶向下的语法分析第4章 自顶向下的语法分析
第4章 自顶向下的语法分析
tjpucompiler
?
香港六合彩
香港六合彩香港六合彩
香港六合彩
香港六合彩 香港六合彩
?
Fux8923
Fux8923Fux8923
Fux8923
香港六合彩 香港六合彩
?
香港六合彩
香港六合彩香港六合彩
香港六合彩
deygsi
?
指考甲公式
指考甲公式指考甲公式
指考甲公式
zoayzoay
?
学测公式
学测公式学测公式
学测公式
zoayzoay
?
颁语言学习100例实例程序
颁语言学习100例实例程序颁语言学习100例实例程序
颁语言学习100例实例程序
yiditushe
?
第3章矩阵及其运算
第3章矩阵及其运算第3章矩阵及其运算
第3章矩阵及其运算
eterou
?
20200323 - AI Intro
20200323 - AI Intro20200323 - AI Intro
20200323 - AI Intro
Jamie (Taka) Wang
?
Ihome inaction 篇外篇之fp介绍
Ihome inaction 篇外篇之fp介绍Ihome inaction 篇外篇之fp介绍
Ihome inaction 篇外篇之fp介绍
dennis zhuang
?
第1章 Matlab操作基础
第1章  Matlab操作基础第1章  Matlab操作基础
第1章 Matlab操作基础
eterou
?
对偶分解与拉格朗日松弛在自然语言处理推理的应用导论
对偶分解与拉格朗日松弛在自然语言处理推理的应用导论对偶分解与拉格朗日松弛在自然语言处理推理的应用导论
对偶分解与拉格朗日松弛在自然语言处理推理的应用导论
zhaoweihb
?
【逆转胜】数学学测总复习讲义
【逆转胜】数学学测总复习讲义【逆转胜】数学学测总复习讲义
【逆转胜】数学学测总复习讲义
lungtengtech
?
诲蝉辫肠丑01资料结构资料结构资料结构资料结构资料结构资料结构资料结构资料结构.辫辫迟
诲蝉辫肠丑01资料结构资料结构资料结构资料结构资料结构资料结构资料结构资料结构.辫辫迟诲蝉辫肠丑01资料结构资料结构资料结构资料结构资料结构资料结构资料结构资料结构.辫辫迟
诲蝉辫肠丑01资料结构资料结构资料结构资料结构资料结构资料结构资料结构资料结构.辫辫迟
LinPhil
?
人机对弈编程概述
人机对弈编程概述人机对弈编程概述
人机对弈编程概述
勇浩 赖
?
实验一 Mathematica软件介绍
实验一   Mathematica软件介绍实验一   Mathematica软件介绍
实验一 Mathematica软件介绍
guestfe33f0e
?
实验一 Mathematica软件介绍
实验一   Mathematica软件介绍实验一   Mathematica软件介绍
实验一 Mathematica软件介绍
Xin Zheng
?
第4章 自顶向下的语法分析
第4章 自顶向下的语法分析第4章 自顶向下的语法分析
第4章 自顶向下的语法分析
tjpucompiler
?
香港六合彩
香港六合彩香港六合彩
香港六合彩
deygsi
?
指考甲公式
指考甲公式指考甲公式
指考甲公式
zoayzoay
?
颁语言学习100例实例程序
颁语言学习100例实例程序颁语言学习100例实例程序
颁语言学习100例实例程序
yiditushe
?
第3章矩阵及其运算
第3章矩阵及其运算第3章矩阵及其运算
第3章矩阵及其运算
eterou
?

锁具装箱

  • 1. 1 题目 某厂生产一种弹子锁具,每个锁具有n个槽,每个槽有m个高度,每个槽的高 度从{1,2,…,m}这m个数(单位略)中任取一个,限制至少有一个相邻的槽 高之差等于m-1,且至少有3个不同的槽高。每个槽的高度取遍这m个数且满足上 面这两个限制时生产出一批锁。 对于同一批中两个锁具是否能够互开,有以下试验结果:若二者相对应的 n 个槽的高度中有 n-1 个相同,另一个槽的高度差为 1,则能互开,在其它情形下 不可能互开。将这一批锁按槽高数之和分为奇数(A)和偶数(B)两类。请给出这 两类锁之间的最大匹配。 2 分析 1. 求出所有满足条件的锁,和为奇数的保存在矩阵 LMA 中, 和为偶数的保存 在矩阵 LMB 中,这样我们便得到了锁与自然数的映射(矩阵行标)。 2. 建立邻接矩阵,若可以互开则设置相应位置为 1 否则设为 0. 3. 利用 Edmonds 算法求完美匹配。 ? 两个数组记录匹配,设 MatA,MatB。例如 MatA(i)=j 表示 A 中第 i 个 元素与 B 中的第 j 个元素相匹配(此时必须有 MatB(j)=i) 。 ? 三个数组 XYZ 用来求某个未匹配点的增广轨。 ? 具体过程有: a) 初始化 MatA,MatB,X,Y,Z 为 0; b) 若 MatA 中不存在 0 元素,则表明匹配已经是最大匹配,算法结束。 若 A 中存在未匹配点,任取一未匹配点 i。 c) 将 i 所有相邻结点在 Y 中标记为 i。 d) 若 Y 与 Z 相同,表明 i 没有与之相应的匹配,将 MatA(i)标记为-1, 转至 b。否则设 Y-Z 中第一个元素的下标为 j。若 j 不在匹配中, 则得到一个增广轨 P,从 j 开始逆向得到一条边在匹配和非匹配 中交替出现的路径,取匹配为原匹配与该增广轨的对称差,转至 b。 e) 若 j 在匹配中,则标记 Z(j)=Y(j)。假设 MatB(j)=i(即与 j 相匹 配的元素为 i),记 X(i)=j,并转至 c。 f) 清空 XYZ,转至 b。 3 实现 Edmonds 算法(匈牙利算法)的关键在于寻找增广轨并求原匹配与该增广轨 的对称差,下面结合代码详细说明增广轨的求法:
  • 2. 1. 首先寻找初始匹配,为方便起见可以选取 A 中第一个元素,代码实现: j = find(AB(1,:), 1); MatA(1)=j; MatB(j)=1; 2. 接着只要 MatA 中存在 0 元素就表明 A 中存在尚未匹配点(不能匹配的点用-1 表示) , 为方便起见可以选取第一个 0 元素(设下标为 i)为下次进行匹配的 点,代码如下: while length(find(MatA==0)) ~= 0 % 存在不匹配的元素 J = find(MatA==0); i = J(1); % 第 i 个元素未被匹配 init = i; 3. 标记 X(i)=0 (标记为 0 方便逆向寻找增广轨,可以做为终结条件),并标记 Y 中所有 与 i 相邻的结点为 i,代码如下: X(i)=0; J = find(AB(i,:)); % J 为所有与 i 相邻结点 Y(J) = i; j=J(1); 4. 当 Y=Z 时表明不存在 i 的匹配,此时清空 XYZ 并标记 MatA(i)=-1 继续下次尚 未匹配点的 匹配, 否则当 j 在匹配中时, 标记 Z(j)=Y(j),设与 j 匹配的点为 i, 标记 Y 中所有 I 相邻的结点,并记 Y-Z 中第一个元素的下标为 j。代码如下: if MatB(j) ~= 0 % j 是匹配点 Z(j) = Y(j); i = MatB(j); X(i)=j; J = find(AB(i,:)); Y(J)=i; J = find(Y); JJ = find(Z); J = setxor(intersect(J, JJ), J); j=J(1); 5. 如果 j 不在匹配中,则表明已经找到了一个增广轨,接下来就是要用原匹配 与增广轨的 对称差来替代原来的匹配, 例如最后一次 i=8, 时发现 MatB(8)=0 j=8 (即 8 不在匹配中) ,之后便可以利用 X 和 Z 中的数据来得到一条增广轨: 下标 1 2 3 4 5 6 7 8 X 0 3B 1B 6B Y NM Z 1A 6A 5A
  • 3. 得到增广轨后便更新原来匹配,其具体代码实现: i = Y(j); MatA(i) = j; MatB(j) = i; while X(i) j = X(i); i = Z(j); MatA(i) = j; MatB(j) = i; end break; 6. 最后为方便人机交互,可以用 Matlab GUI 设计简单的界面。 function pushbutton1_Callback(hObject, eventdata, handles) a = get(handles.edit1, 'String'); b = get(handles.edit2, 'String'); str = Edmonds(str2num(a), str2num(b)); set(handles.edit4, 'String', str); guidata(hObject, handles); 4 结果 槽数 4 5 高度 4 32 180 5 50 378
  • 5. 5 改进 从结果中可以看到当有 5 个槽 5 个高度时匹配有 378 个,此时建立邻接矩阵 为大于 378*378 的矩阵,随着槽数和高度的增加,该程序对内存空间的要求会很 高,而矩阵中真正有用的标记并不多,故空间利用率是很低的,但此方法的优点 在于可以充分利用 Matlab 的内建函数,思路清晰代码简洁。一种改进方法是不 用邻接矩阵, 令每个结点对应一个由其邻接结点构成的向量,这样便可减少空间 需求,同时代码量也会增加,对编程能力要求较高。 6 源码 LockMap.m function [LMA, LMB] = LockMap(n, m) % LOCKMAP - 求解满足条件锁并设置相应的映射 % 输入参数:n 表槽数,m 表高度数。 % 输出参数:LMA,LMB 分别为二维矩阵表示自然数到满足条件锁之间的映射。 global jiA ouB ary A B mm N % 调用递归函数时要用到的变量所以 % 设为全局 N = n; mm = m; jiA=0; ouB=0; A=[]; B=[]; ary = zeros(1, n); RecuCal(n); LMA=A; LMB=B; [lena, n] = size(LMA); [lenb, n] =size(LMB); if lena>lenb temp = LMA; LMA=LMB;LMB=temp; temp = lena;lena=lenb;lenb=temp; end RecuCal.m function RecuCal(n) % RECUCAL - 递归函数 global jiA ouB ary A B mm N if n ==1 for k=1:mm
  • 6. ary(1) = k; Max = max(ary); Min = min(ary); num = 0; neighbor = 0; for i=1:N num = num + (Max-ary(i))*(ary(i)-Min); if (i~=N) neighbor = max(neighbor, abs(ary(i)-ary(i+1))); end end if (neighbor > mm-1.5)&&(num > 0.5) if mod(sum(ary), 2) % 奇数,属于 A 类 jiA = jiA+1; A(jiA,:) = ary; else % 偶数,属于 B 类 ouB = ouB+1; B(ouB,:) = ary; end end end else for k=1:mm ary(n) = k; RecuCal(n-1); end end BuildMatrix.m function AB = BuildMatrix(LMA, LMB) % BUILDMATRIX - 建立邻接矩阵,若 i 与 j 之间可以互开则 AB(i,j)=1,否则为 0。 AB = []; [lena, n] = size(LMA); [lenb, n] =size(LMB); for i = 1:lena for j=1:lenb tmp = 0; for k=1:n tmp = tmp + abs(LMA(i,k)-LMB(j,k)); end if tmp == 1 AB(i, j)=1; end
  • 7. end end Edmonds.m function str = Edmonds(n, m) % EDMONDS - Edmonds 算法寻找完美匹配 str = []; [LMA, LMB] = LockMap(n, m); AB = BuildMatrix(LMA, LMB); lena = length(LMA); lenb = length(LMB); if lena==0 disp('其中一个分组为空, 无法匹配'); %当 n=m=3 时只有偶数组无奇数组,不能完成 匹配 return; end MatA = zeros(1, lena); MatB = zeros(1, lenb); X = MatA; Y=MatB; Z=Y; NumNoMat = 0; % 无法匹配的点的个数 % 最初匹配,只有一个匹配 j = find(AB(1,:), 1); MatA(1)=j; MatB(j)=1; while length(find(MatA==0)) ~= 0 % 存在不匹配的元素 J = find(MatA==0); i = J(1); % 第 i 个元素未被匹配 init = i; X(i)=0; J = find(AB(i,:)); % J 为所有与 i 相邻结点 Y(J) = i; j=J(1); while ~isempty(find(Y~=Z)) if MatB(j) ~= 0 % j 是匹配点 Z(j) = Y(j); i = MatB(j); X(i)=j; J = find(AB(i,:)); Y(J)=i; J = find(Y); JJ = find(Z); J = setxor(intersect(J, JJ), J); j=J(1); else % j 不是匹配点 i = Y(j);
  • 8. MatA(i) = j; MatB(j) = i; while X(i) j = X(i); i = Z(j); MatA(i) = j; MatB(j) = i; end break; end end % 如果 Y==Z 则表明该点没有与之相应的匹配,即不存在完美匹配,在 MatA 中标 % 记为-1。 if isempty(find(Y~=Z, 1)) NumNoMat = NumNoMat + 1; MatA(init) = -1; end X(1:lena)=0; Y(1:lenb)=0; Z=Y; end total = 0; for i=1:lena k = MatA(i); if k<=0 continue; end % k<=0 时表明匹配不存在 stra = ''; strb = ''; for j=1:n stra = [stra, num2str(LMA(i, j)), ' ']; strb = [strb, num2str(LMB(k, j)), ' ']; end str = [str, stra, '------ ', strb, 10]; total = total + 1; end str = [str, '匹配个数有:', num2str(total)]; GUI1.m function varargout = GUI1(varargin) gui_Singleton = 1; gui_State = struct('gui_Name', mfilename, ... 'gui_Singleton', gui_Singleton, ... 'gui_OpeningFcn', @GUI1_OpeningFcn, ... 'gui_OutputFcn', @GUI1_OutputFcn, ... 'gui_LayoutFcn', [] , ... 'gui_Callback', []); if nargin && ischar(varargin{1}) gui_State.gui_Callback = str2func(varargin{1});
  • 9. end if nargout [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); else gui_mainfcn(gui_State, varargin{:}); end % End initialization code - DO NOT EDIT % --- Executes just before GUI1 is made visible. function GUI1_OpeningFcn(hObject, eventdata, handles, varargin) handles.output = hObject; guidata(hObject, handles); function varargout = GUI1_OutputFcn(hObject, eventdata, handles) varargout{1} = handles.output; function pushbutton1_Callback(hObject, eventdata, handles) a = get(handles.edit1, 'String'); b = get(handles.edit2, 'String'); str = Edmonds(str2num(a), str2num(b)); set(handles.edit4, 'String', str); guidata(hObject, handles); function edit1_Callback(hObject, eventdata, handles) input = str2num(get(hObject, 'String')); guidata(hObject, handles); function edit1_CreateFcn(hObject, eventdata, handles) if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) set(hObject,'BackgroundColor','white'); end
  • 10. function edit2_Callback(hObject, eventdata, handles) input = str2num(get(hObject, 'String')); guidata(hObject, handles); function edit2_CreateFcn(hObject, eventdata, handles) if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) set(hObject,'BackgroundColor','white'); end function slider1_Callback(hObject, eventdata, handles) function slider1_CreateFcn(hObject, eventdata, handles) if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) set(hObject,'BackgroundColor',[.9 .9 .9]); end function text_result_Callback(hObject, eventdata, handles) function text_result_CreateFcn(hObject, eventdata, handles) if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) set(hObject,'BackgroundColor','white'); end function edit4_Callback(hObject, eventdata, handles) function edit4_CreateFcn(hObject, eventdata, handles)
  • 11. if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) set(hObject,'BackgroundColor','white'); end function pushbutton2_Callback(hObject, eventdata, handles) set(handles.edit4, 'String', ''); set(handles.edit1, 'String', ''); set(handles.edit2, 'String', '');