洛谷—— P1074 靶形数独

https://www.luogu.org/problem/show?pid=1074

题目描述

小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他

们想用数独来一比高低。但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,

Z 博士拿出了他最近发明的“靶形数独”,作为这两个孩子比试的题目。

靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9 个 3 格宽×3 格

高的小九宫格(用粗黑色线隔开的)。在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入 1 到 9 的数字。每个数字在每个小九宫格内不能

重复出现,每个数字在每行、每列也不能重复出现。但靶形数独有一点和普通数独不同,即

每一个方格都有一个分值,而且如同一个靶子一样,离中心越近则分值越高。(如图)

上图具体的分值分布是:最里面一格(黄色区域)为 10 分,黄色区域外面的一圈(红

色区域)每个格子为 9 分,再外面一圈(蓝色区域)每个格子为 8 分,蓝色区域外面一圈(棕

色区域)每个格子为 7 分,最外面一圈(白色区域)每个格子为 6 分,如上图所示。比赛的

要求是:每个人必须完成一个给定的数独(每个给定数独可能有不同的填法),而且要争取

更高的总分数。而这个总分数即每个方格上的分值和完成这个数独时填在相应格上的数字

的乘积的总和

总分数即每个方格上的分值和完成这个数独时填在相应格上的数字

的乘积的总和。如图,在以下的这个已经填完数字的靶形数独游戏中,总分数为 2829。游戏规定,将以总分数的高低决出胜负。

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

够得到的最高分数。

输入输出格式

输入格式:

一共 9 行。每行 9 个整数(每个数都在 0―9 的范围内),表示一个尚未填满的数独方

格,未填的空格用“0”表示。每两个数字之间用一个空格隔开。

输出格式:

输出文件 sudoku.out 共 1 行。

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

输入输出样例

输入样例#1:

sudoku1
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

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

输出样例#1:

sudoku1
2829

sudoku2
2852

说明

【数据范围】

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

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

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

NOIP 2009 提高组 第四题

记录需要搜索的点,即未填数的点,挨个搜索

从第一个未填数点开始搜

 1 #include <cstdio>
 2
 3 int op[9][9]={{6,6,6,6,6,6,6,6,6},
 4               {6,7,7,7,7,7,7,7,6},
 5               {6,7,8,8,8,8,8,7,6},
 6               {6,7,8,9,9,9,8,7,6},
 7               {6,7,8,9,10,9,8,7,6},
 8               {6,7,8,9,9,9,8,7,6},
 9               {6,7,8,8,8,8,8,7,6},
10               {6,7,7,7,7,7,7,7,6},
11               {6,6,6,6,6,6,6,6,6}};
12 int pos[9][9]={{0,0,0,1,1,1,2,2,2},
13               {0,0,0,1,1,1,2,2,2},
14               {0,0,0,1,1,1,2,2,2},
15               {3,3,3,4,4,4,5,5,5},
16               {3,3,3,4,4,4,5,5,5},
17               {3,3,3,4,4,4,5,5,5},
18               {6,6,6,7,7,7,8,8,8},
19               {6,6,6,7,7,7,8,8,8},
20               {6,6,6,7,7,7,8,8,8}};
21 int map[9][9],ans=-1;
22 int vx[82],vy[82],cnt;
23 bool h[9][10],l[9][10],g[9][10];
24
25 int where(int i,int j)
26 {
27     if(i<3&&j<3) return 0;
28     else if(i<3&&j<6) return 1;
29     else if(i<3&&j<9) return 2;
30     else if(i<6&&j<3) return 3;
31     else if(i<6&&j<6) return 4;
32     else if(i<6&&j<9) return 5;
33     else if(j<3) return 6;
34     else if(j<6) return 7;
35     else if(j<9) return 8;
36 }
37
38 void DFS(int num)
39 {
40     if(num>cnt)
41     {
42         int tmp=0;
43         for(int i=0; i<9; ++i)
44           for(int j=0; j<9; ++j)
45               tmp+=map[i][j]*op[i][j];
46         ans=ans>tmp?ans:tmp;
47         return ;
48     }
49     int tox=vx[num],toy=vy[num],topos=pos[tox][toy];
50     for(int i=1; i<=9; ++i)
51     {
52         if(!h[tox][i]&&!l[toy][i]&&!g[topos][i])
53         {
54             h[tox][i]=1;
55             l[toy][i]=1;
56             g[topos][i]=1;
57             map[tox][toy]=i;
58             DFS(num+1);
59             h[tox][i]=0;
60             l[toy][i]=0;
61             g[topos][i]=0;
62             map[tox][toy]=0;
63         }
64     }
65 }
66
67 int AC()
68 {
69     for(int i=0; i<9; ++i)
70         for(int j=0; j<9; ++j)
71         {
72             scanf("%d",&map[i][j]);
73             if(!map[i][j])
74             {
75                 vx[++cnt]=i;
76                 vy[cnt]=j;
77             }
78             else
79             {
80                 h[i][map[i][j]]=1;
81                 l[j][map[i][j]]=1;
82                 g[pos[i][j]][map[i][j]]=1;
83             }
84         }
85     DFS(1); printf("%d\n",ans);
86     return 0;
87 }
88
89 int Aptal=AC();
90 int main(){;}

TLE6个点,70分

改变搜索顺序,从最后一个未填数点开始搜

 1 #include <cstdio>
 2
 3 const int op[9][9]={{6,6,6,6,6,6,6,6,6},
 4                     {6,7,7,7,7,7,7,7,6},
 5                     {6,7,8,8,8,8,8,7,6},
 6                       {6,7,8,9,9,9,8,7,6},
 7                       {6,7,8,9,10,9,8,7,6},
 8                       {6,7,8,9,9,9,8,7,6},
 9                       {6,7,8,8,8,8,8,7,6},
10                       {6,7,7,7,7,7,7,7,6},
11                       {6,6,6,6,6,6,6,6,6}};
12 const int pos[9][9]={{0,0,0,1,1,1,2,2,2},
13                     {0,0,0,1,1,1,2,2,2},
14                       {0,0,0,1,1,1,2,2,2},
15                       {3,3,3,4,4,4,5,5,5},
16                       {3,3,3,4,4,4,5,5,5},
17                       {3,3,3,4,4,4,5,5,5},
18                       {6,6,6,7,7,7,8,8,8},
19                       {6,6,6,7,7,7,8,8,8},
20                       {6,6,6,7,7,7,8,8,8}};
21 int map[9][9],ans=-1;
22 int vx[82],vy[82],cnt;
23 bool h[9][10],l[9][10],g[9][10];
24
25 void DFS(int num)
26 {
27     if(!num)
28     {
29         int tmp=0;
30         for(int i=0; i<9; ++i)
31           for(int j=0; j<9; ++j)
32               tmp+=map[i][j]*op[i][j];
33         ans=ans>tmp?ans:tmp;
34         return ;
35     }
36     int tox=vx[num],toy=vy[num],topos=pos[tox][toy];
37     for(int i=1; i<=9; ++i)
38     {
39         if(!h[tox][i]&&!l[toy][i]&&!g[topos][i])
40         {
41             h[tox][i]=1;
42             l[toy][i]=1;
43             g[topos][i]=1;
44             map[tox][toy]=i;
45             DFS(num-1);
46             h[tox][i]=0;
47             l[toy][i]=0;
48             g[topos][i]=0;
49             map[tox][toy]=0;
50         }
51     }
52 }
53
54 int AC()
55 {
56     for(int i=0; i<9; ++i)
57         for(int j=0; j<9; ++j)
58         {
59             scanf("%d",&map[i][j]);
60             if(!map[i][j])
61             {
62                 vx[++cnt]=i;
63                 vy[cnt]=j;
64             }
65             else
66             {
67                 h[i][map[i][j]]=1;
68                 l[j][map[i][j]]=1;
69                 g[pos[i][j]][map[i][j]]=1;
70             }
71         }
72     DFS(cnt); printf("%d\n",ans);
73     return 0;
74 }
75
76 int Aptal=AC();
77 int main(){;}

TLE1个点,95分

增加搜索状态,记录当前的得分,如果当前得分+9*10<ans,说明这样填数不可能会搜到最优解

判断搜索层数,快超时的时候return、、、

 1 #include <cstdio>
 2
 3 const int op[9][9]={{6,6,6,6,6,6,6,6,6},
 4                     {6,7,7,7,7,7,7,7,6},
 5                     {6,7,8,8,8,8,8,7,6},
 6                       {6,7,8,9,9,9,8,7,6},
 7                       {6,7,8,9,10,9,8,7,6},
 8                       {6,7,8,9,9,9,8,7,6},
 9                       {6,7,8,8,8,8,8,7,6},
10                       {6,7,7,7,7,7,7,7,6},
11                       {6,6,6,6,6,6,6,6,6}};
12 const int pos[9][9]={{0,0,0,1,1,1,2,2,2},
13                     {0,0,0,1,1,1,2,2,2},
14                       {0,0,0,1,1,1,2,2,2},
15                       {3,3,3,4,4,4,5,5,5},
16                       {3,3,3,4,4,4,5,5,5},
17                       {3,3,3,4,4,4,5,5,5},
18                       {6,6,6,7,7,7,8,8,8},
19                       {6,6,6,7,7,7,8,8,8},
20                       {6,6,6,7,7,7,8,8,8}};
21 int vx[82],vy[82],cnt,deep;
22 int map[9][9],ans=-1,fraction;
23 bool h[9][10],l[9][10],g[9][10];
24
25 void DFS(int num,int now_fraction)
26 {
27     if(!num)
28     {
29         ans=ans>now_fraction?ans:now_fraction;
30         return ;
31     }
32     if(++deep>1e7) return ;
33     if(num*9*10+now_fraction<ans) return ;
34     int tox=vx[num],toy=vy[num],topos=pos[tox][toy],tmp;
35     for(int i=1; i<=9; ++i)
36     {
37         if(!h[tox][i]&&!l[toy][i]&&!g[topos][i])
38         {
39             h[tox][i]=1;
40             l[toy][i]=1;
41             g[topos][i]=1;
42             map[tox][toy]=i;
43             DFS(num-1,now_fraction+map[tox][toy]*op[tox][toy]);
44             h[tox][i]=0;
45             l[toy][i]=0;
46             g[topos][i]=0;
47             map[tox][toy]=0;
48         }
49     }
50 }
51
52 int AC()
53 {
54     for(int i=0; i<9; ++i)
55         for(int j=0; j<9; ++j)
56         {
57             scanf("%d",&map[i][j]);
58             if(!map[i][j])
59             {
60                 vx[++cnt]=i;
61                 vy[cnt]=j;
62             }
63             else
64             {
65                 h[i][map[i][j]]=1;
66                 l[j][map[i][j]]=1;
67                 g[pos[i][j]][map[i][j]]=1;
68                 fraction+=op[i][j]*map[i][j];
69             }
70         }
71     DFS(cnt,fraction);
72     printf("%d\n",ans);
73     return 0;
74 }
75
76 int Aptal=AC();
77 int main(){;}

AC

时间: 2024-10-27 08:02:08

洛谷—— P1074 靶形数独的相关文章

洛谷 P1074 靶形数独

P1074 靶形数独 题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z 博士拿出了他最近发明的“靶形数独”,作为这两个孩子比试的题目. 靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9 个 3 格宽×3 格 高的小九宫格(用粗黑色线隔开的).在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入 1 到 9 的数字.每

洛谷P1074 靶形数独

题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z 博士拿出了他最近发明的“靶形数独”,作为这两个孩子比试的题目. 靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9 个 3 格宽×3 格 高的小九宫格(用粗黑色线隔开的).在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入 1 到 9 的数字.每个数字在每个小九宫格内

洛谷OJ P1074 靶形数独 解题报告

洛谷OJ P1074 靶形数独 解题报告 by MedalPluS 题目描述  小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,Z 博士拿出了他最近发明的“靶形数独”,作为这两个孩子比试的题目. 靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9 个 3 格宽×3 格高的小九宫格(用粗黑色线隔开的).在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,

P1074 靶形数独

P1074 靶形数独正着搜80分,完全倒置95分,完全倒置后左右再倒置,就会A掉,到时候脑洞要大一些. 1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<algorithm> 5 #include<cmath> 6 #include<ctime> 7 #include<set> 8 #include<map> 9 #incl

P1074 靶形数独题解

题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,Z 博士拿出了他最近发明的“靶形数独”,作为这两个孩子比试的题目. 靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有9 个 3 格宽×3 格高的小九宫格(用粗黑色线隔开的).在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入 1 到 9的数字.每个数字在每个小九宫格内不能重复出

Luogu P1074靶形数独

一个需要(存储和优化)技巧的暴力DFS. ·在这里,我们不DFS图的状态:我们选择记录所有空位(记录其位置,属于哪个宫,分数),然后枚举每个空位放 $ 1-9 $ 之内的数. 这里还有一个剪枝的思路:由于DFS是一个树状结构,一层一层往下扩展,所以显然让初始 $ 0 $ 越少的行,DFS的层次越靠上才好.这样能避免大量的扩展枝节,而又不牺牲正确性(因为答案与DFS顺序无关): 所以:首先在读入时记录每行的空位数(初始 $ 0 $ 的数量,保存在数组 n [ 0 ] 中) for(int i(1)

P1074 靶形数独(爆搜)

说是爆搜,却还是有点技巧 首先数独应该有个想法,从最有可能填上数字的那些地方开始 也就是说哪些行0最少,就从那儿开始 为了最大限度地利用已有信息,就先把所有0的位置扣出来单独填 最后别忘了回溯就行 但是这种做法仍然过不了下面这个样例: 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 00 0 0 0 0 0 0

洛谷 【P1074】靶形数独

P1074 靶形数独 题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z 博士拿出了他最近发明的“靶形数独”,作为这两个孩子比试的题目. 靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9 个 3 格宽×3 格 高的小九宫格(用粗黑色线隔开的).在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入 1 到 9 的数字.每

洛谷P1784 数独

To 洛谷.1784 数独(类似(或者说相同)题:CODEVS.4966 简单数独(4*4数独) CODEVS.2924 数独挑战) 题目描述 数独是根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行.每一列.每一个粗线宫内的数字均含1-9,不重复.每一道合格的数独谜题都有且仅有唯一答案,推理方法也以此为基础,任何无解或多解的题目都是不合格的. 芬兰一位数学家号称设计出全球最难的“数独游戏”,并刊登在报纸上,让大家去挑战. 这位数学家说,他相信只有“智慧最顶尖”的人才有可能破解这