[NOIP2009 提高组] 靶形数独

题目背景

此为远古题,不保证存在可以通过任意符合要求的输入数据的程序

题目描述

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

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

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

总分数即每个方格上的分值和完成这个数独时填在相应格上的数字的乘积的总和。如图,在以下的这个已经填完数字的靶形数独游戏中,总分数为 2829。游戏规定,将以总分数的高低决出胜负。

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

输入格式

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

输出格式

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

样例 #1

样例输入 #1

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

样例输出 #1

2829

样例 #2

样例输入 #2

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

样例输出 #2

2852

提示

数据规模与约定

  • 对于 40 % 40\% 40% 的数据,数独中非 0 0 0 数的个数不少于 30 30 30;
  • 对于 80 % 80\% 80% 的数据,数独中非 0 0 0 数的个数不少于 26 26 26;
  • 对于 100 % 100\% 100% 的数据,数独中非 0 0 0 数的个数不少于 24 24 24。

我真的太喜欢大法师啦()

#TLE就是大法师的赞歌!!!!!!

大致思路

根据题意,我们需要判断横向,纵向及一个3x3矩形内是否有重复元素,因此,我们可以开三个二维数组对其进行储存。用近似打表(?)的方式存储权值。

int x[15][15],y[15][15],xy[15][15],va[12][12]={{0,0,0,0,0,0,0,0,0,0,0,0,},
{0,6,6,6,6,6,6,6,6,6,},
{0,6,7,7,7,7,7,7,7,6,},
{0,6,7,8,8,8,8,8,7,6,},
{0,6,7,8,9,9,9,8,7,6,},
{0,6,7,8,9,10,9,8,7,6,},
{0,6,7,8,9,9,9,8,7,6,},
{0,6,7,8,8,8,8,8,7,6,},
{0,6,7,7,7,7,7,7,7,6,},
{0,6,6,6,6,6,6,6,6,6,},
},a[12][12];

9x9的矩形中有9个3x3的小矩形,我们可以用函数来完成当前坐标属于那个矩形的判断

int sl(int x,int y){if(x<=3){if(y<=3)return 1;if(y<=6)return 2;if(y<=9)return 3;}if(x<=6){if(y<=3)return 4;if(y<=6)return 5;if(y<=9)return 6;}if(x<=9){if(y<=3)return 7;if(y<=6)return 8;if(y<=9)return 9;}
}

dfs部分

显而易见,我们的数独排列从一行中已经有数的开始搜索可以更好地缩小搜索树,我们可以对搜索顺序进行规划。

bool cmp(int a,int b){return num[a]>num[b];
}
for(int i=1;i<=9;i++){sortxu[i]=i;for(int j=1;j<=9;j++){cin>>a[i][j];if(a[i][j]){x[i][a[i][j]]=y[a[i][j]][j]=xy[sl(i,j)][a[i][j]]=1;num[i]++;}}}sort(sortxu+1,sortxu+10,cmp);

剩下的基本就只需套dfs模板啦。

void dfs(int xx,int yy,int sum,int xu){if(yy==10){//换行if(xu==9){//搜索完毕ans=max(sum,ans);return;}dfs(sortxu[xu+1],1,sum,xu+1);//下一行搜索return;}if(xx>=10||yy>=10)return;//边界int ju=sl(xx,yy);//判断当前属于那个3x3小矩形if(a[xx][yy]){dfs(xx,yy+1,sum+a[xx][yy]*va[xx][yy],xu);}//当前位置之前已经有数else //没数,枚举for(int l=1;l<=9;l++){if(x[xx][l]==0&&y[l][yy]==0&&xy[ju][l]==0){x[xx][l]=y[l][yy]=xy[ju][l]=1;dfs(xx,yy+1,sum+l*va[xx][yy],xu);x[xx][l]=y[l][yy]=xy[ju][l]=0;//回溯}}
}

斯巴拉西

AC CODE

#include<bits/stdc++.h>
using namespace std;
int num[10],sortxu[10],ans=-1;
int x[15][15],y[15][15],xy[15][15],va[12][12]={{0,0,0,0,0,0,0,0,0,0,0,0,},
{0,6,6,6,6,6,6,6,6,6,},
{0,6,7,7,7,7,7,7,7,6,},
{0,6,7,8,8,8,8,8,7,6,},
{0,6,7,8,9,9,9,8,7,6,},
{0,6,7,8,9,10,9,8,7,6,},
{0,6,7,8,9,9,9,8,7,6,},
{0,6,7,8,8,8,8,8,7,6,},
{0,6,7,7,7,7,7,7,7,6,},
{0,6,6,6,6,6,6,6,6,6,},
},a[12][12];
int sl(int x,int y){if(x<=3){if(y<=3)return 1;if(y<=6)return 2;if(y<=9)return 3;}if(x<=6){if(y<=3)return 4;if(y<=6)return 5;if(y<=9)return 6;}if(x<=9){if(y<=3)return 7;if(y<=6)return 8;if(y<=9)return 9;}
}
bool cmp(int a,int b){return num[a]>num[b];
}
void dfs(int xx,int yy,int sum,int xu){if(yy==10){//换行if(xu==9){//搜索完毕ans=max(sum,ans);return;}dfs(sortxu[xu+1],1,sum,xu+1);//下一行搜索return;}if(xx>=10||yy>=10)return;//边界int ju=sl(xx,yy);//判断当前属于那个3x3小矩形if(a[xx][yy]){dfs(xx,yy+1,sum+a[xx][yy]*va[xx][yy],xu);}//当前位置之前已经有数else //没数,枚举for(int l=1;l<=9;l++){if(x[xx][l]==0&&y[l][yy]==0&&xy[ju][l]==0){x[xx][l]=y[l][yy]=xy[ju][l]=1;dfs(xx,yy+1,sum+l*va[xx][yy],xu);x[xx][l]=y[l][yy]=xy[ju][l]=0;//回溯}}
}
int main(){for(int i=1;i<=9;i++){sortxu[i]=i;for(int j=1;j<=9;j++){cin>>a[i][j];if(a[i][j]){x[i][a[i][j]]=y[a[i][j]][j]=xy[sl(i,j)][a[i][j]]=1;num[i]++;}}}sort(sortxu+1,sortxu+10,cmp);dfs(sortxu[1],1,0,1);cout<<ans;return 0;
}

#10025 「一本通 1.3 练习 4」靶形数独P1074 [NOIP2009 提高组]相关推荐

  1. 「一本通 6.5 练习 3」迷路

    「一本通 6.5 练习 3」迷路 题目描述 大意说一个给你有向图, 一个有n个节点,每个节点相连的边为所需要花费的时间, 问你从1到n 在时间刚好为t是的方案数.输出%2009 注意:不能在某个节点逗 ...

  2. 【C++】「一本通 1.1 例 4」加工生产调度

    「一本通 1.1 例 4」加工生产调度 [来源] [题目描述] [输入格式] [输出格式] [输入样例] [输出样例] [数据范围] [解析] [代码] [来源] 一本通题库-1425 LibreOJ ...

  3. LibreOJ10082. 「一本通 3.3 例 1」Word Rings【二分+SPFA】

    10082. 「一本通 3.3 例 1」Word Rings [题目描述] 传送门 [题解] 将一个字符串看成一条边,字符两端的字符看成节点,长度看成权值.二分枚举答案,最后SPFA刷正环,因为只要有 ...

  4. #10016. 「一本通 1.2 练习 3」灯泡(三分)

    参考博客链接:「一本通 1.2 练习 3」灯泡(三分) #include<stdio.h> #include<string.h> #include<math.h> ...

  5. 【C++】「一本通 1.1 例 2」种树

    「一本通 1.1 例 2」种树 [来源] [题目描述] [输入格式] [输出格式] [输入样例] [输出样例] [解析] [代码] [来源] 一本通题库-1423 LibreOJ-10001 vjud ...

  6. #10001. 「一本通 1.1 例 2」种树

    #10001. 「一本通 1.1 例 2」种树 满足n个区间种树的要求,求最少种多少棵数 思路 按照区间的尾巴来排序,因为如果区间有重叠的种在第一个区间的尾巴可以使得种树更少,所有每次始从尾巴开始种树 ...

  7. 【C++】「一本通 1.1 例 5」智力大冲浪

    「一本通 1.1 例 5」智力大冲浪 [来源] [题目描述] [输入格式] [输出格式] [输入样例] [输出样例] [数据范围] [解析] [代码] [来源] 一本通题库-1426 LibreOJ- ...

  8. 「一本通 1.2 例 2」Best Cow Fences

    题目链接: 链接: [link](信息学奥赛一本通(C++版)在线评测系统). 首先这道题要求找平均数,且要求所选片段长度需要大于等于l.那么首先想到的就是最暴力的方法就是找到所有大于等于l的片段在其 ...

  9. LOJ #10222. 「一本通 6.5 例 4」佳佳的 Fibonacci

    题目链接 题目大意 $$F[i]=F[i-1]+F[i-2]\ (\ F[1]=1\ ,\ F[2]=1\ )$$ $$T[i]=F[1]+2F[2]+3F[3]+...+nF[n]$$ 求$T[n] ...

最新文章

  1. 树状数组与离散化与求第K大模板
  2. 46.Express框架 GET 方法和POST 方法
  3. linux反调试代码,linux反调试方法
  4. tf.nn.embedding_lookup
  5. python 多进程 每个进程做不同功能实例_Python 多进程并发操作中进程池Pool的实例...
  6. php 命令设计模式示例,php设计模式(十九)命令模式-Fun言
  7. ERROR 2003 (HY000): Can't connect to MySQL server on '192.168.33.10' (111) 解决方法
  8. 【渝粤教育】国家开放大学2018年秋季 2208T政治学原理 参考试题
  9. Google docs支持上传任何文档包括pdf...Cool!
  10. 手机怎么打开html页面,手机网页打不开怎么办?看了就知道了!
  11. 微信公众号:提示“redirect_uri 参数错误”
  12. 普通电脑用u盘安装服务器系统安装教程,Windows Server 2016使用U盘安装需要哪些步骤 硬盘安装Windows Server 2016图文教程...
  13. 计算方法-常微分方程初值问题的数值解法
  14. 【投屏】Scrcpy源码分析三(Client篇-投屏阶段)
  15. UnicodeEncodeError: 'gbk' codec can't encode character '\xa9' in position 314810: illegal multibyte
  16. Python学习之路:列表(List)的append()、extend()与insert()方法
  17. 100725B Banal Tickets
  18. 英勇的战士——斯巴达
  19. 2023年注会最全椰子思维导图
  20. Pico 的安卓自启动

热门文章

  1. jenkins启动报错 Job for jenkins.service failed because the control process exited with error code.
  2. 世界人工智能大会大咖云集,共商赋能传统企业数字化转型之路
  3. java服务器内部出错_服务器遇到内部错误,导致无法完成此请求
  4. unity接微信登录,eclipse打jar包,快速高效
  5. 妙飞:拥有空杯心态终身学习才能走得更远
  6. Metanet 开发者指南
  7. css hover控制其他元素
  8. 算法 - KMP算法原理顿悟有感
  9. 交互式脚本遍历ip和密码登录到主机执行任何命令通用版、执行交互式脚本报错root@xxx‘s password: missing close-bracket处理方法
  10. 从零开始学google地图API(1)--获取api_key并显示google地图