利用抹点法对闭回路算法编程

编程语言:MATLAB

定理储备:

1.每个空格都对应唯一的闭回路,该闭回路以所在空格为起点,其余结点全是数字格;

2.闭回路上每个结点的行和列上至少(除本身外)还有一个结点。

算法:设(i,j)为空格,为了寻找(i,j)的闭回路,可以将(i,j)设为数字格,抹去行和列上只有一个数字格的的点,反复遍历,直到未抹去的点的行和列上至少有2个数字格。

代码实现:

function [Sigma] = lockcircle1(h_,l_,A_x,B)
%lockcircle 求取闭回路

%h_所要求取的闭回路起点行索引
%l_所要求取的闭回路起点列索引
%A_x为基变量标识矩阵(为基变量则对应位置为1,反之为0)

A_x(h_,l_)=1;
[A_c,A_r]=size(A_x);
change=1;
node=0;

%抹点法求闭回路

%当无法抹去点时得到所有闭回路所经过的节点
while(change>0)
    change=0;
    for i=1:A_c
        for j=1:A_r
            if(A_x(i,j)==1&&hl(i,j,A_c,A_r,A_x))
                A_x(i,j)=0;
                change=change+1;
            end
        end
    end
end

for i=1:A_c
    for j=1:A_r
        if(A_x(i,j)==1)
            node=node+1;
        end
    end
end

%得到闭回路的排序序列
po=[];
po(1,1)=h_;%po(2,1)是空格所处列,po(1,1)是空格所处行
po(2,1)=l_;
A_x(h_,l_)=0;
for p=1:node-1
    finish=0;
    for i=1:A_c
        if(A_x(i,po(2,p))==1)
            po(1,p+1)=i;
            po(2,p+1)=po(2,p);
            A_x(i,po(2,p))=0;
            finish=1;%在列上找到了数字格
            break;
        end
    end
    if(finish==0)
        for j=1:A_r
            if(A_x(po(1,p),j)==1)
                po(1,p+1)=po(1,p);
                po(2,p+1)=j;
                A_x(po(1,p),j)=0;
                break;
            end
        end
    end
end
Sigma=0;
for p=1:node
    if(mod(p,2)==0)
        B(po(1,p),po(2,p))=-B(po(1,p),po(2,p));
    end
    Sigma=Sigma+B(po(1,p),po(2,p));
end
end

function [A]=ClosedloopAdjustment(h_,l_,A)
%闭回路调整法
A_x=~isnan(A);
A_x(h_,l_)=1;
[A_c,A_r]=size(A_x);
change=1;
node=0;
%当无法抹去点时得到所有闭回路所经过的节点
while(change>0)
    change=0;
    for i=1:A_c
        for j=1:A_r
            if(A_x(i,j)==1&&hl(i,j,A_c,A_r,A_x))
                A_x(i,j)=0;
                change=change+1;
            end
        end
    end
end

for i=1:A_c
    for j=1:A_r
        if(A_x(i,j)==1)
            node=node+1;
        end
    end
end
%得到闭回路的排序序列
po=[];
po(1,1)=h_;
po(2,1)=l_;
A_x(h_,l_)=0;
for p=1:node-1
    finish=0;
    for i=1:A_c
        if(A_x(i,po(2,p))==1)
            po(1,p+1)=i;
            po(2,p+1)=po(2,p);
            A_x(i,po(2,p))=0;
            finish=1;
            break;
        end
    end
    if(finish==0)
        for j=1:A_r
            if(A_x(po(1,p),j)==1)
                po(1,p+1)=po(1,p);
                po(2,p+1)=j;
                A_x(po(1,p),j)=0;
                break;
            end
        end
    end
end
%以(_h,_l_)为调入格,得到新的调运表
a=[];
po_=[];
po_(:,1)=po(:,2);
a(1)=A(po_(1,1),po_(2,1));
%%取po的偶数列po_
for p=1:node
    if mod(p,2)==0
        i=p/2;
        po_(1,i)=po(1,p);
        po_(2,i)=po(2,p);
    end
end
%%取闭回路上具有(-1)的数字格的最小者
for i=1:node/2
    a(i)=A(po_(1,i),po_(2,i));
    [min_a,index]=min(a);
end
%%按闭回路上的正负号加上或减去该值
A(po(1,1),po(2,1))=0;
A(po(1,2*index),po(2,2*index))=NaN;
for i=1:node
    if mod(i,2)~=0
        A(po(1,i),po(2,i))= A(po(1,i),po(2,i))+min_a;
    else
        A(po(1,i),po(2,i))= A(po(1,i),po(2,i))-min_a;
    end
end
end

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值