赞
踩
小明天资聪颖,酷爱数学,尤其擅长做数独游戏。不过普通的数独游戏已经满足不了小明了,于是他发明了一种“金字塔数独”:
下图即为金字塔数独。和普通数独一样,在9×9的大九宫格中有9个3×3的小九宫格(用粗黑色线隔开的)。要求每个格子上都有一个 1 到 9 的数字,每个数字在每个小九宫格内不能重复出现,每个数字在每行、每列也不能重复出现。
但金字塔数独的每一个格子都有一个分值,类似金字塔的俯视图。如图所示,白色格子为6分,蓝色格子为 7分,绿色格子为 8 分,紫色格子为 9 分,红色格子为 10 分。颜色相同的格子分值一样,离中心越近则分值越高。
金字塔数独的总分等于每个格子上的数字和对应的分值乘积之和。现在小明给定金字塔数独的若干数字,请问如何填写,可以使得金字塔数独的总分最高。
输入一共9行。每行输入 9 个整数(每个数都在 0—9的范围内),每两个整数之间用一个空格隔开,“0”表示该格子为空。
输出为一行,输出一个整数,代表金字塔数独的最高总分。
如果数独无解,则输出-1。
0 0 0 0 0 0 0 0 0
0 0 3 0 0 0 9 0 0
7 9 0 0 0 2 0 1 3
0 0 9 1 5 0 0 0 0
0 7 4 0 2 6 1 3 9
0 0 6 0 0 0 0 0 0
6 0 0 0 0 7 0 0 0
3 1 0 4 0 5 7 9 6
0 0 7 0 0 1 0 4 0
2864
先预处理金字塔中每个点的分值,然后DFS搜索所有可能的解,并维护所有解中的最高分。
#include <bits/stdc++.h> using namespace std; typedef long long ll; int ans = 0; int a[10][10]; int val[10][10]; // 金字塔中每个点的分值 bool is = 0; // 是否有解 bool check(int x, int y, int v) // 检查该填写是否符合数独规则 { // 判断行与列是否满足 for (int i = 0; i < 9; i++) { if (a[x][i] == v) return 0; if (a[i][y] == v) return 0; } // 判断九宫格是否满足 int s = x / 3 * 3; int t = y / 3 * 3; for (int i = s; i < s + 3; i++) { for (int j = t; j < t + 3; j++) { if (a[i][j] == v) return 0; } } // 如果都符合,返回1 return 1; } void dfs(int x, int y, int sum) // 递归到第x行,第y列,总分为sum { if (x == 9) // 如果能递归完所有行,说明找到了一个解 { is = 1; // 有解 ans = max(ans, sum); // 维护ans为所有数独填写方案中的最高分 return; } if (y == 9) // 如果递归完该行所有列,递归下一行 dfs(x + 1, 0, sum); else { if (a[x][y]) // 如果该位置已填入数字,继续递归 dfs(x, y + 1, sum + val[x][y] * a[x][y]); else { // 遍历1到9所有数字,判断该填入是否符合条件 for (int i = 1; i <= 9; i++) { if (check(x, y, i)) // 如果符合条件,继续递归 { a[x][y] = i; dfs(x, y + 1, sum + val[x][y] * a[x][y]); a[x][y] = 0; // 回溯 } } } } } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); // 预处理9×9的金字塔中每个点的分值 int num = 6; for (int k = 0; k < 4; k++) { for (int i = k, j = k; j < 8 - k; j++) { val[i][j] = num; } for (int i = k, j = 8 - k; i < 8 - k; i++) { val[i][j] = num; } for (int i = 8 - k, j = 8 - k; j > k; j--) { val[i][j] = num; } for (int i = 8 - k, j = k; i > k; i--) { val[i][j] = num; } num++; } val[4][4] = num; // 读入数据,从第0行第0列开始读入 for (int i = 0; i < 9; i++) for (int j = 0; j < 9; j++) cin >> a[i][j]; dfs(0, 0, 0); // 从第0行第0列总分为0开始递归 if (is) cout << ans; else cout << -1; return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。