P1784 数独

点击查看代码
#include <bits/stdc++.h>
using namespace std;

int a[10][10]; // 存数独地图
bool row[10][10], col[10][10], block[3][3][10]; // 三个记账本,标记题目要求的三个状态

// 打印函数
void print() {
    for(int i=1; i<=9; i++) {
        for(int j=1; j<=9; j++) cout << a[i][j] << " ";
        cout << endl;
    }
    exit(0); // 填完一种方案就可以直接结束程序了,不用找所有解
}
//1.状态定义,就是棋盘的每个棋子的坐标
void dfs(int x, int y) {
    //2.截止条件与换行逻辑,这里是相互统一的
    //y到了一定地步才可以换行
    if (y == 10) {
        dfs(x + 1, 1);
        return;
    }

    if (x == 10) {
        print();
        return;
    }

    //4.和下面的for循环算是枚举和选择的逻辑,不是剪枝,因为这是逻辑的必须
    if (a[x][y] != 0) {
        // 直接跳过,去填下一个
        dfs(x, y + 1);
        return;
    }

    for (int k = 1; k <= 9; k++) {
        // 计算九宫格的坐标
        int bx = (x - 1) / 3;
        int by = (y - 1) / 3;

        // 选择逻辑的一部分,三个标记
        if (!row[x][k] && !col[y][k] && !block[bx][by][k]) {
            //5.回溯三件套
            // A. 标记 (Make Move)
            a[x][y] = k;
            row[x][k] = true;
            col[y][k] = true;
            block[bx][by][k] = true;

            // B. 递归
            dfs(x, y + 1);

            // C. 回溯 (Unmake Move) - 非常重要!
            a[x][y] = 0;
            row[x][k] = false;
            col[y][k] = false;
            block[bx][by][k] = false;
        }
    }
}

int main() {
    // 读入数据顺便标记这个数字对应的行列和九宫格的标记情况
    for(int i=1; i<=9; i++) {
        for(int j=1; j<=9; j++) {
            cin >> a[i][j];
            if(a[i][j] != 0) {
                int k = a[i][j];
                row[i][k] = true;
                col[j][k] = true;
                block[(i-1)/3][(j-1)/3][k] = true;
            }
        }
    }

    dfs(1, 1);
    return 0;
}
posted @ 2026-01-07 00:35  gosaky  阅读(0)  评论(0)    收藏  举报