2009年10月31日 星期六

數獨


//------------------單行數獨------------------

const int N = 9;
int M[N] = {0,1,0,3,0,8,0,2,5};
int nHole, hole[N*N];

bool bPack (int n)                      //是否可將 n 填入 M 裡
{
    for (int i=0; i<N; i++)             //若 M 中已存在 n
        if (n == M[i]) return false;    //則返回 false
    return true;
}

void fillHole (int pos)                 //將 M 中的空位填滿
{
    int i, x;
    if (pos == nHole) {                 //若空位皆已填滿
        for (i=0; i<N; i++)
            cout << M[i];               //便印出解答
        puts(""); return;               //然後返回
    }
    for (i=1; i<=N; i++) {              //嘗試在 M[x] 處填入 1~N
        x = hole[pos];                  //取得空洞位置
        if (bPack (i)) {                //若可用 i 填起來
            M[x] = i;                   //就令 M[x] = i
            fillHole (pos+1);           //繼續填下一個洞   
            M[x] = 0;                   //將 M[x] 還原, 待以用
        }                               //其他值去嘗試填入
    }
}

int main()
{
    for (int i=0; i<N; i++)
        if (0==M[i])                    //將 M 中 0 的位置
            hole [nHole++] = i;         //記錄在 hole 裡
    fillHole (0);
}

多行的就像這樣....
同理,可擴展至 N*N*N*....N 的解法。

//------------------多行數獨------------------

const int N = 9;

int nHole = 0;
int hole [N*N];

int M[N][N] =
    {0,0,4,0,0,8,0,2,5,
     2,0,0,0,0,0,9,0,0,
     0,0,6,0,0,5,0,0,0,
     5,7,0,0,6,0,0,0,0,
     1,0,0,0,4,0,0,0,8,
     0,0,0,0,2,0,0,3,7,
     0,0,0,3,0,0,8,0,0,
     0,0,7,0,0,0,0,0,1,
     6,2,0,9,0,0,4,0,0};

bool bPack (int x, int y, int n)            //是否可將 n 填入 M[y][x] 裡
{
    for (int i=0; i<N; i++)                 //若 M[0~N-1][x]
        if (n == M[i][x] || n == M[y][i])   //或 M[y][0~N-1] 中已存在 n
            return false;                   //則返回 false
    return true;
}

void fillHole (int pos)                     //將 M 中的空位填滿
{
    int i, x, y;
    if (pos == nHole) {                     //若空位皆已填滿
        for (i=0; i<N*N; i++) {             //便印出解答   
            if (0 == i%N) puts("");         //每印 N 個就換行
            cout << M[0][i];               
        }
        puts(""); getch(); return;          //然後返回
    }
    for (i=1; i<=N; i++) {                  //嘗試在 M[y][x] 處填入 1~N
        y = (x=hole[pos]) / N;              //取得空洞位置 y 座標
        x %= N;                             //取得空洞位置 x 座標
        if (bPack (x,y,i)) {                //若 M[y][x] 可用 i 填起來
            M[y][x] = i;                    //就令 M[y][x] = i
            fillHole (pos+1);               //繼續填下一個洞   
            M[y][x] = 0;                    //將 M[y][x] 還原,
        }                                   //待以用其他值去嘗試填入
    }
}
int main ()
{
    for (int i=0; i<N*N; i++)
        if (0 == M[0][i])                   //將 M 中 0 的位置
            hole [nHole++] = i;             //記錄在 hole 裡
    fillHole (0);
}

沒有留言:

張貼留言