24h購物| | PChome| 登入
2011-08-13 07:29:10| 人氣1,913| 回應0 | 上一篇 | 下一篇

目前世界最快-解數獨的程序, 個人實作

推薦 0 收藏 0 轉貼0 訂閱站台

數據結構 : Dancing Links
將數獨盤面, 轉成矩陣, 變成了一個精準覆蓋問題,
要控制的有
1.該盤面存在的位置 (1~81 位置填上 1)
2.每一行, 所在的 1~9 ( 82~162 位置填上 1, 9 行中, 它填哪一行, 填什麼數字)
3.每一列, 所在的 1~9 (163~243 位置填上 1,
9 列中, 它填哪一列, 填什麼數字)
4.每一個方格, 所在的 1~9 (244~324位置填上 1)
因此, 每一格可能的解, 將由 4 個元素為 1 的控制

× 個人實作, 優化可能還做得不好, 可能還有所缺漏

範例輸入 :
3
0 6 0 1 0 4 0 5 0
0 0 8 3 0 5 6 0 0
2 0 0 0 0 0 0 0 1
8 0 0 4 0 7 0 0 6
0 0 6 0 0 0 3 0 0
7 0 0 9 0 1 0 0 4
5 0 0 0 0 0 0 0 2
0 0 7 2 0 6 9 0 0
0 4 0 5 0 8 0 7 0
3
0 0 3 9 0 0 7 6 0
0 4 0 0 0 6 0 0 9
6 0 0 0 1 0 0 0 4
0 0 0 6 7 0 0 9 0
0 0 4 0 0 5 6 0 0
0 1 0 0 4 9 0 0 0
7 0 0 0 9 0 2 0 0
3 0 0 2 0 0 0 4 0
0 2 0 0 0 8 5 0 0
範例輸出 :
==================
9 6 3 1 7 4 2 5 8
1 7 8 3 2 5 6 4 9
2 5 4 6 8 9 7 3 1
8 2 1 4 3 7 5 9 6
4 9 6 8 5 2 3 1 7
7 3 5 9 6 1 8 2 4
5 8 9 7 1 3 4 6 2
3 1 7 2 4 6 9 8 5
6 4 2 5 9 8 1 7 3
TOTAL SOLUTION : 1
==================
1 5 3 9 8 4 7 6 2
2 4 7 5 3 6 1 8 9
6 9 8 7 1 2 3 5 4
8 3 2 6 7 1 4 9 5
9 7 4 8 2 5 6 3 1
5 1 6 3 4 9 8 2 7
7 6 5 4 9 3 2 1 8
3 8 1 2 5 7 9 4 6
4 2 9 1 6 8 5 7 3
==================
1 5 3 9 8 4 7 6 2
2 4 7 5 3 6 1 8 9
6 9 8 7 1 2 3 5 4
8 3 2 6 7 1 4 9 5
9 7 4 8 2 5 6 3 1
5 1 6 3 4 9 8 2 7
7 8 5 4 9 3 2 1 6
3 6 1 2 5 7 9 4 8
4 2 9 1 6 8 5 7 3
==================
1 5 3 9 8 4 7 6 2
2 4 8 7 3 6 1 5 9
6 9 7 5 1 2 3 8 4
8 3 2 6 7 1 4 9 5
9 7 4 8 2 5 6 3 1
5 1 6 3 4 9 8 2 7
7 6 5 4 9 3 2 1 8
3 8 1 2 5 7 9 4 6
4 2 9 1 6 8 5 7 3
==================
1 5 3 9 8 4 7 6 2
2 4 8 7 3 6 1 5 9
6 9 7 5 1 2 3 8 4
8 3 2 6 7 1 4 9 5
9 7 4 8 2 5 6 3 1
5 1 6 3 4 9 8 2 7
7 8 5 4 9 3 2 1 6
3 6 1 2 5 7 9 4 8
4 2 9 1 6 8 5 7 3
==================
1 5 3 9 8 4 7 6 2
2 4 8 7 3 6 1 5 9
6 9 7 5 1 2 8 3 4
8 3 2 6 7 1 4 9 5
9 7 4 3 2 5 6 1 8
5 1 6 8 4 9 3 2 7
7 6 5 4 9 3 2 8 1
3 8 1 2 5 7 9 4 6
4 2 9 1 6 8 5 7 3
==================
1 5 3 9 8 4 7 6 2
2 4 8 7 3 6 1 5 9
6 9 7 5 1 2 8 3 4
8 3 2 6 7 1 4 9 5
9 7 4 3 2 5 6 8 1
5 1 6 8 4 9 3 2 7
7 6 5 4 9 3 2 1 8
3 8 1 2 5 7 9 4 6
4 2 9 1 6 8 5 7 3
==================
1 5 3 9 8 4 7 6 2
2 4 8 7 3 6 1 5 9
6 9 7 5 1 2 8 3 4
8 3 2 6 7 1 4 9 5
9 7 4 3 2 5 6 8 1
5 1 6 8 4 9 3 2 7
7 8 5 4 9 3 2 1 6
3 6 1 2 5 7 9 4 8
4 2 9 1 6 8 5 7 3
==================
1 5 3 9 8 4 7 6 2
8 4 2 7 3 6 1 5 9
6 9 7 5 1 2 3 8 4
2 3 8 6 7 1 4 9 5
9 7 4 8 2 5 6 3 1
5 1 6 3 4 9 8 2 7
7 6 5 4 9 3 2 1 8
3 8 1 2 5 7 9 4 6
4 2 9 1 6 8 5 7 3
==================
1 5 3 9 8 4 7 6 2
8 4 2 7 3 6 1 5 9
6 9 7 5 1 2 3 8 4
2 3 8 6 7 1 4 9 5
9 7 4 8 2 5 6 3 1
5 1 6 3 4 9 8 2 7
7 8 5 4 9 3 2 1 6
3 6 1 2 5 7 9 4 8
4 2 9 1 6 8 5 7 3
==================
1 5 3 9 8 4 7 6 2
8 4 2 7 3 6 1 5 9
6 9 7 5 1 2 8 3 4
2 3 8 6 7 1 4 9 5
9 7 4 3 2 5 6 1 8
5 1 6 8 4 9 3 2 7
7 6 5 4 9 3 2 8 1
3 8 1 2 5 7 9 4 6
4 2 9 1 6 8 5 7 3
==================
1 5 3 9 8 4 7 6 2
8 4 2 7 3 6 1 5 9
6 9 7 5 1 2 8 3 4
2 3 8 6 7 1 4 9 5
9 7 4 3 2 5 6 8 1
5 1 6 8 4 9 3 2 7
7 6 5 4 9 3 2 1 8
3 8 1 2 5 7 9 4 6
4 2 9 1 6 8 5 7 3
==================
1 5 3 9 8 4 7 6 2
8 4 2 7 3 6 1 5 9
6 9 7 5 1 2 8 3 4
2 3 8 6 7 1 4 9 5
9 7 4 3 2 5 6 8 1
5 1 6 8 4 9 3 2 7
7 8 5 4 9 3 2 1 6
3 6 1 2 5 7 9 4 8
4 2 9 1 6 8 5 7 3
==================
1 5 3 9 8 4 7 6 2
8 4 7 5 2 6 1 3 9
6 9 2 7 1 3 8 5 4
5 3 8 6 7 2 4 9 1
9 7 4 1 3 5 6 2 8
2 1 6 8 4 9 3 7 5
7 6 5 4 9 1 2 8 3
3 8 1 2 5 7 9 4 6
4 2 9 3 6 8 5 1 7
TOTAL SOLUTION : 13

/************************************************************************/
#include<stdio.h>

#include<stdlib.h>
#define Maxv 100000
struct DacingLinks {
    int left, right;
    int up, down;
    int data, ch, rh;
}DL[100001 + 1001];
int s[1001], o[1001], head, size, time;
int n, m, a, b, c, tn;
void Remove(int c) {
    DL[DL[c].right].left = DL[c].left;
    DL[DL[c].left].right = DL[c].right;
    int i, j;
    for(i = DL[c].down; i != c; i = DL[i].down) {
        for(j = DL[i].right; j != i; j = DL[j].right) {
            DL[DL[j].down].up = DL[j].up;
            DL[DL[j].up].down = DL[j].down;
            s[DL[j].ch]--;
        }
    }
}
void Resume(int c) {
    int i, j;
    for(i = DL[c].down; i != c; i = DL[i].down) {
        for(j = DL[i].left; j != i; j = DL[j].left) {
            DL[DL[j].down].up = j;
            DL[DL[j].up].down = j;
            s[DL[j].ch]++;
        }
    }
    DL[DL[c].right].left = c;
    DL[DL[c].left].right = c;
}
void Print_board(int k) {
    static int set[81], a, b;
    for(a = 0; a < n; a++)
        printf("==");
    puts("");
    for(a = 0; a < k; a++) {
        set[DL[o[a]].data] = DL[o[a]].rh+1;
    }
    for(a = 0; a < n; a++) {
        for(b = 0; b < n; b++) {
            printf("%d ", set[a*9+b]);
        }
        puts("");
    }
}
void DFS(int k) {
    if(time > 10000000) return ;
    if(DL[head].right == head) {
        Print_board(k);
        time++;
        return;
    }
    int t = Maxv, c, i, j;
    for(i = DL[head].right; i != head; i = DL[i].right) {
        if(s[i] < t) {
            t = s[i], c = i;
        }
    }
    Remove(c);
    for(i = DL[c].down; i != c; i = DL[i].down) {
        o[k] = i;
        for(j = DL[i].right; j != i; j = DL[j].right)
            Remove(DL[j].ch);
        DFS(k+1);
        for(j = DL[i].left; j != i; j = DL[j].left)
            Resume(DL[j].ch);
    }
    Resume(c);
}
int new_node(int up, int down, int left, int right) {
    DL[size].up = up, DL[size].down = down;
    DL[size].left = left, DL[size].right = right;
    DL[up].down = DL[down].up = DL[left].right = DL[right].left = size;
    return size++;
}
void new_row(int n, int Row[], int rh, int set) {
    int a, r, row = -1, k;
    for(a = 0; a < n; a++) {
        r = Row[a];
        DL[size].ch = r, DL[size].data = set, s[r]++;
        if(row == -1) {
            row = new_node(DL[DL[r].ch].up, DL[r].ch, size, size);
            DL[row].rh = rh;
        }else {
            k = new_node(DL[DL[r].ch].up, DL[r].ch, DL[row].left, row);
            DL[k].rh = rh;
        }
    }
}
void init(int m) {
    size = 0;
    head = new_node(0, 0, 0, 0);
    int i;
    for(i = 1; i <= m; i++) {
        new_node(i, i, DL[head].left, head);
        DL[i].ch = i, s[i] = 0;
    }
}
main() {
    int map[10][10], Row[10], t;
    while(scanf("%d", &n) == 1) {
        tn = n, n *= n, m = n*n*4, init(m);
        for(a = 0; a < n; a++)
            for(b = 0; b < n; b++) {
                scanf("%d", &map[a][b]);
                if(map[a][b] == 0) {
                    for(c = 0; c < n; c++) {
                        t = 0;
                        Row[t++] = a*n + b + 1;
                        Row[t++] = n*n + a*n + c + 1;
                        Row[t++] = 2*n*n+ b*n + c + 1;
                        Row[t++] = 3*n*n+ (a/tn*tn + b/tn)*n + c + 1;
                        new_row(t, Row, c, a*n+b);
                        /*printf("%d ", a*9 + b + 1);/*原始牌面上的標記
                        printf("%d ", 81 + a*9 + c + 1);/*行上1~9的標記
                        printf("%d ", 162+ b*9 + c + 1);/*列上1~9的標記
                        printf("%d ", 243+ (a/3*3 + b/3)*9 + c + 1);/*方格中1~9的標記
                        puts("");*/
                    }
                } else {
                    c = map[a][b]-1, t = 0;
                    Row[t++] = a*n + b + 1;
                    Row[t++] = n*n + a*n + c + 1;
                    Row[t++] = 2*n*n+ b*n + c + 1;
                    Row[t++] = 3*n*n+ (a/tn*tn + b/tn)*n + c + 1;
                    new_row(t, Row, c, a*n+b);
                    /*printf("%d ", a*9 + b + 1);/*原始牌面上的標記
                    printf("%d ", 81 + a*9 + c + 1);/*行上1~9的標記
                    printf("%d ", 162+ b*9 + c + 1);/*列上1~9的標記
                    printf("%d ", 243+ (a/3*3 + b/3)*9 + c + 1);/*方格中1~9的標記
                    puts("");*/
                }
            }
        time = 0, DFS(0);
        if(time)    printf("TOTAL SOLUTION : %d\n", time);
        else    puts("NO SOLUTION");
    }
    return 0;
}
/*
3
0 6 0 1 0 4 0 5 0
0 0 8 3 0 5 6 0 0
2 0 0 0 0 0 0 0 1
8 0 0 4 0 7 0 0 6
0 0 6 0 0 0 3 0 0
7 0 0 9 0 1 0 0 4
5 0 0 0 0 0 0 0 2
0 0 7 2 0 6 9 0 0
0 4 0 5 0 8 0 7 0

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


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

台長: Morris
人氣(1,913) | 回應(0)| 推薦 (0)| 收藏 (0)| 轉寄
全站分類: 不分類 | 個人分類: 其他題目 |
此分類下一篇:[中興資工][程設][作業HW13]
此分類上一篇:[手動][大數][三角函數] sin x 運算

是 (若未登入"個人新聞台帳號"則看不到回覆唷!)
* 請輸入識別碼:
請輸入圖片中算式的結果(可能為0) 
(有*為必填)
TOP
詳全文