[NOIP2009] 靶形数独(搜索+剪枝)

题目描述

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

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

  • 看完题目,貌似没有什么更好的解决方法,那就搜索了。
  • 但是通过观察数据范围,如果没有什么好的搜索策略,复杂度大概为O(sum^9),这不是个理想的策略。
  • 简单易想的剪枝策略:一边搜一边判断,大概能优化很多,期望得分60分。
  • 通过题意可以得出一个较好的搜索策略:根据每行每列需要搜索的数字个数(即开始数独前未给出数字的格子的个数)统计出来,根据个数从小到大排序,得出一个较好的行列搜索顺序。
  • 然后就搜吧!
  • 期望得分100分。
  1 #include <cstdio>
  2 #include <algorithm>
  3 using namespace std;
  4
  5 struct ha{
  6     int m,cnt;
  7 } a[15];
  8
  9 struct li{
 10     int m,cnt;
 11 } b[15];
 12
 13 bool cmp1(const ha x,const ha y) {
 14     return (x.cnt>y.cnt);
 15 }
 16
 17 bool cmp2(const li x,const li y) {
 18     return x.cnt>y.cnt;
 19 }
 20
 21 const int w[10][10]=
 22     {0,0,0,0,0,0,0,0,0,0,
 23     0,6,6,6,6,6,6,6,6,6,
 24     0,6,7,7,7,7,7,7,7,6,
 25     0,6,7,8,8,8,8,8,7,6,
 26     0,6,7,8,9,9,9,8,7,6,
 27     0,6,7,8,9,10,9,8,7,6,
 28     0,6,7,8,9,9,9,8,7,6,
 29     0,6,7,8,8,8,8,8,7,6,
 30     0,6,7,7,7,7,7,7,7,6,
 31     0,6,6,6,6,6,6,6,6,6};
 32
 33 const int num[10][10]=
 34     {0,0,0,0,0,0,0,0,0,0,
 35     0,1,1,1,2,2,2,3,3,3,
 36     0,1,1,1,2,2,2,3,3,3,
 37     0,1,1,1,2,2,2,3,3,3,
 38     0,4,4,4,5,5,5,6,6,6,
 39     0,4,4,4,5,5,5,6,6,6,
 40     0,4,4,4,5,5,5,6,6,6,
 41     0,7,7,7,8,8,8,9,9,9,
 42     0,7,7,7,8,8,8,9,9,9,
 43     0,7,7,7,8,8,8,9,9,9};
 44
 45 int n=9,x,tot,kashi,ans=-1,sum=0,map[15][15],quex[15],quey[15];
 46 bool f[15][15],hang[15][15],lie[15][15],ge[15][15],wujie,ka;
 47
 48 void dfs(int u,int v) {
 49     if (u>n) {
 50         ans=max(ans,sum);
 51         return;
 52     }
 53     int x=a[u].m;
 54     int y=b[v].m;
 55     if (f[x][y]) {
 56         if (v<n) dfs(u,v+1); else dfs(u+1,1);
 57         return;
 58     }
 59     for (int i=1; i<=9; i++) {
 60         if (hang[x][i]) continue;
 61         if (lie[y][i]) continue;
 62         if (ge[num[x][y]][i]) continue;
 63         hang[x][i]=1;
 64         lie[y][i]=1;
 65         ge[num[x][y]][i]=1;
 66         sum+=w[x][y]*i;
 67         if (v<n) dfs(u,v+1); else dfs(u+1,1);
 68         hang[x][i]=0;
 69         lie[y][i]=0;
 70         ge[num[x][y]][i]=0;
 71         sum-=w[x][y]*i;
 72     }
 73 }
 74
 75 int main() {
 76     for (int i=1; i<=n; i++) {
 77         for (int j=1; j<=n; j++) {
 78             scanf("%d",&x);
 79             if (x) {
 80                 a[i].cnt++;
 81                 b[j].cnt++;
 82                 hang[i][x]=1;
 83                 lie[j][x]=1;
 84                 ge[num[i][j]][x]=1;
 85                 sum+=w[i][j]*x;
 86                 f[i][j]=1;
 87             }
 88         }
 89     }
 90     for (int i=1; i<=n; i++) {
 91         a[i].m=i;
 92         b[i].m=i;
 93     }
 94     sort(a+1,a+n+1,cmp1);
 95     sort(b+1,b+n+1,cmp2);
 96     //for (int i=1; i<=n; i++) printf("%d ",a[i].m);
 97     //for (int i=1; i<=n; i++) printf("%d ",b[i].m);
 98     dfs(1,1);
 99     printf("%d",ans);
100     return 0;
101 }
时间: 2024-10-10 17:22:13

[NOIP2009] 靶形数独(搜索+剪枝)的相关文章

NOIP2009 靶形数独(搜索)

以前做过一道hdu类似的数独题,那道题我没有加什么优化就过了,然后这道题不加优化可以得50~80分,要上80分就必须要优化 可以用位运算保存每一行每一列每个九宫格内已经使用的数,例如userow[i] = 011101111表示第i行还有1,5两个数字没有使用,那么我们枚举每个未知的格子(i,j)时,他不能填的数就是userow[i]|usecol[j]|usebox[i/3*3+j/3] ,其实这样做也不能优化什么时间,下面才是最NB的优化 在输入的时候我们可以统计每一行已知的数,于是我们能够

[NOIP2009] 靶形数独

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

[NOIP2009]靶形数独 题解

407. [NOIP2009] 靶形数独 ★★   输入文件:sudoku.in   输出文件:sudoku.out   简单对比时间限制:5 s   内存限制:128 MB [问题描述] 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z博士请教,Z 博士拿出了他最近发明的“靶形数独” ,作为这两个孩子比试的题目. 靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有 9 个 3 格

[NOIP2009]靶形数独 深搜+枝杈优化

这道题,又是一位玄学搜索...... 我是用的蜗牛序搜的(顾名思义,@,这么搜),我正着搜80然后一反转比原来快了几十倍........一下AC....... 我的思路是这样的话我们可以从内到外或者从外到内搜索,这样的话我们就可以在一定程度上运用贪心,因为中间的价值大外面的价值小,我是作为一个从来没有玩过数独的人的思路...然而任何一个玩过数独的人都会先选可能状态少的优先搜索....... 对于这题里的数据,可行方案很少因此摆在我们面前的不是减去不优的解而是减去不成立的解,然而对于不成立的解在我

【NOIP2009】靶形数独 DLX(Dancing Links)

[NOIP2009]靶形数独 T4 Time Limit: 2 Sec  Memory Limit: 128 MB Description 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向Z 博士请教,Z 博士拿出了他最近发明的"靶形数独",作为这两个孩子比试的题目. 靶形数独的方格同普通数独一样,在 9 格宽×9 格高的大九宫格中有9 个3 格宽×3 格高的小九宫格(用粗黑色线隔开的).在

【NOIP2009】靶形数独

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

靶形数独 (codevs 1174)题解

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

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

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

codevs1174 靶形数独

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