洛谷P1074 靶形数独

题目描述

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

们想用数独来一比高低。但普通的数独对他们来说都过于简单了,于是他们向 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 提高组 第四题

首先需要搜索出所有的数独解,然后每次算出该解对应的靶形数独值,记录最大值即可。

剪枝:存每行、每列、每正方块出现的数的集合h[],r[],block[],对于每个0,求其对应h,r,block的并,就可以很快地知道该位置可以填的数。

剪枝2:↑用位运算处理以上操作。

剪枝3:计算每个0可能可以填的数的数量,每次填可填数量最小的位置。

刚开始没有用位运算,最高卡到90分……

之后加上了剪枝2和3,然而因为剪枝3中最小位置的信息记录错误,无限T……

↑又花了一个小时才查出来错,悲伤。

↑最近怎么尽是犯这些低级错误……

 1 /*by SilverN*/
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 using namespace std;
 7 int sc[10][10]={{0,0,0,0,0,0,0,0,0,0},
 8                 {0,6,6,6,6,6,6,6,6,6},
 9                 {0,6,7,7,7,7,7,7,7,6},
10                 {0,6,7,8,8,8,8,8,7,6},
11                 {0,6,7,8,9,9,9,8,7,6},
12                 {0,6,7,8,9,10,9,8,7,6},
13                 {0,6,7,8,9,9,9,8,7,6},
14                 {0,6,7,8,8,8,8,8,7,6},
15                 {0,6,7,7,7,7,7,7,7,6},
16                 {0,6,6,6,6,6,6,6,6,6}};
17 int mp[15][15];
18 int ans=-1;
19 int block[15],h[15],r[15];
20 int in[15][15];
21 int sx[100],sy[100],cnt=0;
22 inline int blcnt(int x){
23     int res=9;
24     while(x){
25         res-=(x&1);
26         x>>=1;
27     }
28     return res;
29 }
30 void init(){
31     for(int i=1;i<=9;i++)
32      for(int j=1;j<=9;j++)
33         in[i][j]=(i+2)/3*3+(j+2)/3-3;
34 }
35 void dfs(int sum){
36     int i,j;
37     int mini=60,pos=0;
38     int tmp,now;
39     int ctmp;
40     for(i=1;i<=cnt;i++){
41         if(!mp[sx[i]][sy[i]]){
42             tmp=h[sx[i]]|r[sy[i]]|block[in[sx[i]][sy[i]]];
43             now=blcnt(tmp);
44             if(!now)return;
45             if(now<mini){
46                 ctmp=tmp;//记录最小值对应的tmp
47                 //先前由于没有记录ctmp,而在后面计算时用tmp算,出现了bug,费了一个小时查出来错
48                 mini=now;
49                 pos=i;
50             }
51         }
52     }
53     if(mini==60){
54         ans=max(ans,sum);
55         return;
56     }
57     i=sx[pos];
58     j=sy[pos];
59              for(int k=1;k<=9;k++){
60                  if(!(ctmp&(1<<k))){
61                      mp[i][j]=k;
62                      h[i]^=(1<<k);
63                      r[j]^=(1<<k);
64                      block[in[i][j]]^=(1<<k);
65                      dfs(sum+k*sc[i][j]);
66                      //回溯
67                      block[in[i][j]]^=(1<<k);
68                      h[i]^=(1<<k);
69                      r[j]^=(1<<k);
70                      mp[i][j]=0;
71                  }
72              }
73     return;
74 }
75
76 int main(){
77     int i,j;
78     cnt=0;
79     int su=0;
80     init();
81     for(i=1;i<=9;i++)//行
82      for(j=1;j<=9;j++){//列
83          scanf("%d",&mp[i][j]);
84          if(mp[i][j]){
85              r[j]^=1<<mp[i][j];
86              h[i]^=1<<mp[i][j];
87              block[in[i][j]]^=1<<mp[i][j];
88              su+=sc[i][j]*mp[i][j];
89         }
90         else{
91             cnt++;
92             sx[cnt]=i;
93             sy[cnt]=j;
94         }
95     }
96     dfs(su);
97     printf("%d\n",ans);
98     return 0;
99 }
时间: 2024-11-03 22:35:08

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

洛谷 P1074 靶形数独

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

洛谷—— P1074 靶形数独

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

洛谷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,不重复.每一道合格的数独谜题都有且仅有唯一答案,推理方法也以此为基础,任何无解或多解的题目都是不合格的. 芬兰一位数学家号称设计出全球最难的“数独游戏”,并刊登在报纸上,让大家去挑战. 这位数学家说,他相信只有“智慧最顶尖”的人才有可能破解这