[NOIp 2009]靶形数独

Posted NaVi_Awson

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[NOIp 2009]靶形数独相关的知识,希望对你有一定的参考价值。

Description

小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低。但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,Z 博士拿出了他最近发明的“靶形数独”,作为这两个孩子比试的题目。

靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9 个 3 格宽×3 格高的小九宫格(用粗黑色线隔开的)。在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入 1 到 9 的数字。每个数字在每个小九宫格内不能重复出现,每个数字在每行、每列也不能重复出现。但靶形数独有一点和普通数独不同,即每一个方格都有一个分值,而且如同一个靶子一样,离中心越近则分值越高。(如图)

技术分享图片

上图具体的分值分布是:最里面一格(黄色区域)为 10 分,黄色区域外面的一圈(红色区域)每个格子为 9 分,再外面一圈(蓝色区域)每个格子为 8 分,蓝色区域外面一圈(棕色区域)每个格子为 7 分,最外面一圈(白色区域)每个格子为 6 分,如上图所示。比赛的要求是:每个人必须完成一个给定的数独(每个给定数独可能有不同的填法),而且要争取更高的总分数。而这个总分数即每个方格上的分值和完成这个数独时填在相应格上的数字的乘积的总和总分数即每个方格上的分值和完成这个数独时填在相应格上的数字的乘积的总和。如图,在以下的这个已经填完数字的靶形数独游戏中,总分数为 2829。游戏规定,将以总分数的高低决出胜负。

技术分享图片

由于求胜心切,小城找到了善于编程的你,让你帮他求出,对于给定的靶形数独,能够得到的最高分数。

Input

一共 9 行。每行 9 个整数(每个数都在 0―9 的范围内),表示一个尚未填满的数独方格,未填的空格用“0”表示。每两个数字之间用一个空格隔开。

Output

输出可以得到的靶形数独的最高分数。如果这个数独无解,则输出整数-1。

Sample Input

7 0 0 9 0 0 0 0 1 
1 0 0 0 0 5 9 0 0 
0 0 0 2 0 0 0 8 0 
0 0 5 0 2 0 0 0 3 
0 0 0 0 0 0 6 4 8 
4 1 3 0 0 0 0 0 0 
0 0 7 0 0 2 0 9 0 
2 0 1 0 6 0 8 0 4 
0 8 0 5 0 4 0 1 2

Sample Output

2829

HINT

40%的数据,数独中非 0 数的个数不少于 30。

80%的数据,数独中非 0 数的个数不少于 26。

100%的数据,数独中非 0 数的个数不少于 24。

题解

本来想写个$dancing-link$,看到码量就放弃了,爆搜水一下。

 1 //It is made by Awson on 2017.11.10
 2 #include <map>
 3 #include <set>
 4 #include <cmath>
 5 #include <ctime>
 6 #include <queue>
 7 #include <stack>
 8 #include <cstdio>
 9 #include <string>
10 #include <vector>
11 #include <cstdlib>
12 #include <cstring>
13 #include <iostream>
14 #include <algorithm>
15 #define LL long long
16 #define LD long double
17 #define Max(a, b) ((a) > (b) ? (a) : (b))
18 #define Min(a, b) ((a) < (b) ? (a) : (b))
19 #define sqr(x) ((x)*(x))
20 #define y1 yy
21 #define count COUNT
22 using namespace std;
23 const int cost[9][9] = {
24   {6, 6, 6, 6, 6, 6, 6, 6, 6},
25   {6, 7, 7, 7, 7, 7, 7, 7, 6},
26   {6, 7 ,8, 8, 8, 8, 8, 7, 6},
27   {6, 7, 8, 9, 9, 9, 8 ,7, 6},
28   {6, 7, 8, 9, 10, 9, 8, 7, 6},
29   {6, 7, 8, 9, 9, 9, 8, 7, 6},
30   {6, 7, 8, 8, 8, 8, 8, 7, 6},
31   {6, 7, 7, 7, 7, 7, 7, 7, 6},
32   {6, 6, 6, 6, 6, 6, 6, 6, 6}
33 };
34 
35 bool line[9][10], clmn[9][10], gon[3][3][10];
36 int mp[9][9];
37 int x, cnt;
38 int ans = -1;
39 
40 int cul(int mp[9][9]) {
41   int cnt = 0;
42   for (int i = 0; i < 9; i++)
43     for (int j = 0; j < 9; j++)
44       cnt += mp[i][j]*cost[i][j];
45   return cnt;
46 }
47 void dfs(int cnt) {
48   if (cnt == 81) {
49     int cnt = cul(mp); ans = Max(ans, cnt);
50     return;
51   }
52   int locx, locy, step = 9;
53   for (int i = 0; i < 9; i++)
54     for (int j = 0; j < 9; j++)
55       if (!mp[i][j]) {
56       int s = 0;
57       for (int k = 1; k <= 9; k++) if (!line[i][k] && !clmn[j][k] && !gon[i/3][j/3][k]) s++;
58       if (s <= step) step = s, locx = i, locy = j;
59     }
60   for (int k = 1; k <= 9; k++)
61     if (!line[locx][k] && !clmn[locy][k] && !gon[locx/3][locy/3][k]) {
62       line[locx][k] = clmn[locy][k] = gon[locx/3][locy/3][k] = 1;
63       mp[locx][locy] = k;
64       dfs(cnt+1);
65       mp[locx][locy] = 0;
66       line[locx][k] = clmn[locy][k] = gon[locx/3][locy/3][k] = 0;
67     }
68 }
69 void work() {
70   for (int i = 0; i < 9; i++)
71     for (int j = 0; j < 9; j++) {
72       scanf("%d", &x);
73       if (x) cnt++, line[i][x] = 1, clmn[j][x] = 1, gon[i/3][j/3][x] = 1;
74       mp[i][j] = x;
75     }
76   dfs(cnt);
77   printf("%d\n", ans);
78 }
79 int main() {
80     work();
81     return 0;
82 }

 

以上是关于[NOIp 2009]靶形数独的主要内容,如果未能解决你的问题,请参考以下文章

[NOIP2009]靶形数独 题解

[Noip2009] 靶形数独

[NOIp 2009]靶形数独

[NOIP2009]靶形数独 题解

Noip2009靶形数独

NOIP2009 靶形数独