poj2676(数独)

也是一个简单剪枝的dfs。记录所有为0的位置,依次填写,当发现某个空格可选的填写数字已经没有时,说明该支路无效,剪掉。

不算是一个难题吧,但是还是花了不少时间,问题主要出在细节上,行列坐标反了、3乘3小格的位置判断等。写程序一定要细心。

#include <iostream>
using namespace std;

const int MAX_R = 9;
int map[MAX_R + 1][MAX_R + 1];
int zero_pos[MAX_R * MAX_R][2];
int possible_digits[MAX_R * MAX_R][9];
int zero_cnt;

int setPossibleDigits(int x, int y, int s)
{
    bool possible[10];
    memset(possible, 0, sizeof(possible));
    for (int i = 1; i <= MAX_R; i++){
        possible[map[i][x]] = true;
        possible[map[y][i]] = true;
    }
    int subX = (x - 1) / 3;
    int subY = (y - 1) / 3;
    for (int i = subX * 3 + 1; i <= subX * 3 + 3; i++){
        for (int j = subY * 3 + 1; j <= subY * 3 + 3; j++){
            possible[map[j][i]] = true;
        }
    }
    int cnt = 0;
    for (int i = 1; i <= 9; i++){
        if (!possible[i])
            possible_digits[s][cnt++] = i;
    }
    return cnt;
}

bool dfs(int step)
{
    if (step == zero_cnt){
        return true;
    }
    int curX = zero_pos[step][1],
        curY = zero_pos[step][0];
    int possible_cnt = setPossibleDigits(curX, curY, step);
    if (possible_cnt == 0){
        return false;
    }
    for (int i = 0; i < possible_cnt; i++){
        map[curY][curX] = possible_digits[step][i];
        if (dfs(step + 1))
            return true;
        else
            map[curY][curX] = 0;
    }
    return false;
}

int main()
{
    int t;
    cin >> t;
    while (t--){
        memset(map, 0, sizeof(map));
        memset(zero_pos, 0, sizeof(zero_pos));
        memset(possible_digits, 0, sizeof(possible_digits));
        zero_cnt = 0;
        for (int i = 1; i <= MAX_R; i++){
            for (int j = 1; j <= MAX_R; j++){
                char ch;
                cin >> ch;
                map[i][j] = ch - '0';
                if (map[i][j] == 0){
                    zero_pos[zero_cnt][0] = i;
                    zero_pos[zero_cnt++][1] = j;
                }
            }
        }
        dfs(0);
        for (int i = 1; i <= MAX_R; i++){
            for (int j = 1; j <= MAX_R; j++){
                cout << map[i][j];
            }
            cout << endl;
        }
    }
    return 0;
}

 

posted on 2015-10-29 15:09  caiminfeng  阅读(952)  评论(0编辑  收藏  举报

导航