数独

传送门
给出测试组数
再给出未填时的\(9\times 9\)数独情况
输出填完的数独情况
要求每行和每列1-9只能出现一次,且局部\(3\times3\)格中,也满足,而且\(3\times3\)中每个数字需要出现一次

思路,多设了3个数组,用来记录出现的次数
然后从左上角开始搜索,从左到右,满了就到下一行的第一个,直到走到最后一行后,因为是dfs,所以记得回溯

#include <bits/stdc++.h>
const int N = 10;
int G[N][N];
bool hang[N][N], lie[N][N], dyg[N][N], flag;//hang[i][x]表示第i行数字x是否用过,lie[j][x]表示第j列数字x是否用过,dyg[k][x]表示9个3*3的单元格里第k个单元格是否用过
void print(){
    for(int i = 0; i < 9; i++)
        for(int j = 0; j < 9; j++)
            printf("%d%c", G[i][j], " \n"[j == 8]);
}
void dfs(int x,int y){
    if(flag) return;
    if(x == 9){
        flag = 1; print(); return;
    }else{
        if(G[x][y]){
            if(y < 8) dfs(x, y + 1);//向右
            else dfs(x + 1, 0);//一行已经都搜过了,进行下一行搜索
        }else{
            for(int i = 1; i <= 9; i++){
                if(hang[x][i] || lie[y][i] || dyg[x / 3 * 3 + y / 3][i]) continue;
                G[x][y] = i;//保存搜到的数
                hang[x][i] = lie[y][i] = dyg[x / 3 * 3 + y / 3][i] = 1;//标记
                if(y < 8) dfs(x, y + 1);
                else dfs(x + 1, 0);
                G[x][y] = 0;//回溯
                hang[x][i] = lie[y][i] = dyg[x / 3 * 3 + y / 3][i] = 0;
            }
        }
    }
}
void solve(){
    memset(hang, false, sizeof(hang));
    memset(lie, false, sizeof(lie));
    memset(dyg, false, sizeof(dyg));
    flag = 0;
    for(int i = 0;i < 9; i++){
        for(int j = 0; j < 9; j++){
            scanf("%1d", &G[i][j]);
            if(G[i][j] != 0){
                int v = G[i][j];
                hang[i][v] = lie[j][v] = dyg[i / 3 * 3 + j / 3][v] = 1;
            }
        }
    }
    dfs(0, 0);//从第1行第一列开始搜索
}
int main(){
    int t; scanf("%d", &t);
    while(t--) solve();
    return 0;
}

舞蹈链求数独

posted @ 2019-09-13 14:56  Emcikem  阅读(270)  评论(0编辑  收藏  举报