洛谷P1406 方格填数 题解 DFS

题目链接:https://www.luogu.com.cn/problem/P1406

解题思路:
搜索。但是要注意搜索过程中的剪枝,比如一行拼完了之后要检查这一行,最后一行的每一列拼完了之后要检查每一列。然后就是最终要检查两条对角线。每一条线上 (n) 个数之和为所有数之和除以 (n)

示例程序:

#include <bits/stdc++.h>
using namespace std;
int n, a[25], ans[5][5], sum;
bool vis[25];
bool chk_r(int r) {
    int tmp = 0;
    for (int i = 1; i <= n; i ++) tmp += ans[r][i];
    return tmp == sum;
}
bool chk_c(int c) {
    int tmp = 0;
    for (int i = 1; i <= n; i ++) tmp += ans[i][c];
    return tmp == sum;
}
bool chk_o() {
    int tmp1 = 0, tmp2 = 0;
    for (int i = 1; i <= n; i ++) tmp1 += ans[i][i], tmp2 += ans[i][n+1-i];
    return tmp1 == sum && tmp2 == sum;
}
bool dfs(int x, int y) {
    if (x == n+1 && y == 1) {
        return chk_r(n) && chk_c(n) && chk_o();
    }
    if (x > 1 && y == 1 && !chk_r(x-1)) return false;
    if (x == n && y > 1 && !chk_c(y-1)) return false;
    int xx = x, yy = y+1;
    if (y == n) xx = x+1, yy = 1;
    for (int i = 0; i < n*n; i ++) {
        if (!vis[i]) {
            vis[i] = true;
            ans[x][y] = a[i];
            if (dfs(xx, yy)) return true;
            vis[i] = false;
        }
    }
    return false;
}
int main() {
    cin >> n;
    for (int i = 0; i < n*n; i ++) {
        cin >> a[i];
        sum += a[i];
    }
    assert(sum % n == 0);
    sum /= n;
    sort(a, a+n*n);
    assert(dfs(1, 1) == true);
    cout << sum << endl;
    for (int i = 1; i <= n; i ++) {
        for (int j = 1; j <= n; j ++) {
            if (j > 1) cout << " ";
            cout << ans[i][j];
        }
        cout << endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/quanjun/p/14551227.html