洛谷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;
}