DLX算法及應用(二)Matlab解數獨-數組模擬鏈表

這個是用數組模擬鏈表,解數獨專用,非DLX模板

function [ans,times] = DLX_solve_sudoku(problem)
global S L R U D colRoot rowRoot temp times
problem = problem - '0';

times = 0;
S = zeros(1,325);
L = [325,1:324];
R = [2:325,1];
U = 1:325;
D = 1:325;
colRoot = 1:325;
rowRoot = zeros(1,325);

cnt = 325;
for ix = 1:81
    row = ceil(ix/9);
    col = mod(ix-1,9)+1;
    box = 3*(ceil(row/3)-1)+ceil(col/3);
    if problem(ix) == 0
        for val = 1:9
            
            current_col = [ix, 81+9*(row-1)+val, 162+9*(col-1)+val,...
                243+9*(box-1)+val]+1;
            
            L = [L, cnt+4, cnt+1:cnt+3];
            R = [R, cnt+2:cnt+4, cnt+1];
            
            D(U(current_col)) = cnt+1:cnt+4;
            D = [D, current_col];
            U = [U, U(current_col)];
            U(current_col) = cnt+1:cnt+4;
            S(current_col) = S(current_col)+1;
            colRoot = [colRoot, current_col];
            rowRoot = [rowRoot, ones(1,4)*(ix*10+val)];
            cnt = cnt+4;
        end
    else
        val = problem(ix);
        current_col = [ix, 81+9*(row-1)+val, 162+9*(col-1)+val,...
            243+9*(box-1)+val]+1;
        
        L = [L, cnt+4, cnt+1:cnt+3];
        R = [R, cnt+2:cnt+4, cnt+1];
        
        D(U(current_col)) = cnt+1:cnt+4;
        D = [D, current_col];
        U = [U, U(current_col)];
        U(current_col) = cnt+1:cnt+4;
        
        S(current_col) = S(current_col)+1;
        colRoot = [colRoot, current_col];
        rowRoot = [rowRoot, ones(1,4)*(ix*10+val)];
        cnt = cnt+4;
    end
end

temp = zeros(1,81);
flag = search(0);
if flag == 1
    ans = reshape(temp,9,9)';
else ans = -1;
end


end


function flag = search(k)

global S L R D colRoot rowRoot temp

if R(1) == 1
    flag = 1;
    return;
end
minSize = 9999;
c = R(1);
while c ~= 1
    if S(c) < minSize
        minSize = S(c);
        cRoot = c;
        if minSize == 1
            break;
        end
        if minSize == 0
            flag = 0;
            return;
        end
    end
    c = R(c);
end

cover(cRoot);

current_row = D(cRoot);
while current_row ~= cRoot
    
    pos = floor(rowRoot(current_row)/10);
    v = mod(rowRoot(current_row),10);
    temp(pos) = v;
    
    current = R(current_row);
    while current ~= current_row
        cover(colRoot(current));
        current = R(current);
    end
    if search(k+1) == 1
        flag = 1;
        return;
    end
    current = L(current_row);
    while current ~= current_row
        recover(colRoot(current));
        current = L(current);
    end
    current_row = D(current_row);
end

recover(cRoot);

flag = 0;
return;

end

function cover(c)
global S L R U D colRoot times
times = times + 1;
L(R(c)) = L(c);
R(L(c)) = R(c);
i = D(c);
while i ~= c
    j = R(i);
    while j ~= i
        U(D(j)) = U(j);
        D(U(j)) = D(j);
        S(colRoot(j)) = S(colRoot(j)) - 1;
        j = R(j);
    end
    i = D(i);
end
end

function recover(c)
global S L R U D colRoot
i = U(c);
while i ~= c
    j = L(i);
    while j ~= i
        U(D(j)) = j;
        D(U(j)) = j;
        S(colRoot(j)) = S(colRoot(j)) + 1;
        j = L(j);
    end
    i = U(i);
end
L(R(c)) = c;
R(L(c)) = c;
end


示例:

>> DLX_solve_sudoku('800000000003600000070090200050007000000045700000100030001000068008500010090000400')

ans =

     8     1     2     7     5     3     6     4     9
     9     4     3     6     8     2     1     7     5
     6     7     5     4     9     1     2     8     3
     1     5     4     2     3     7     8     9     6
     3     6     9     8     4     5     7     2     1
     2     8     7     1     6     9     5     3     4
     5     2     1     9     7     4     3     6     8
     4     3     8     5     2     6     9     1     7
     7     9     6     3     1     8     4     5     2


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章