一本通&&洛谷 ——靶型数独——题解




主要是搜索顺序不同导致效率千差万别。
联想人做数独的策略,总是先填可填数最少的那个空,再填选择第二少的。。。其实这种策略就造就了一个深度浅时分支也较少的搜索树。合适的搜索顺序再配合剪枝==AC。
所以搜索顺序为:从当前可填数的数目最少的那个空开始。注意:每填一个空,都会导致同行同列同九宫格的空的可填数数目减一,所以不能一开始就排序。(实测这样做会比正解慢8倍左右,真是恐怖如斯)所以要在分支选择时去找。为了平衡准确性与高效性,可以用一个简单的判断找到一个比较合适的空去填(因为如果每次都精确去找那个可填数数目最小的那个空会导致复杂度偏高,因此只要简单地找到可填数数目相对小的那个空就行)。
找一下搜索面临或有关的状态与维度:当前分数v,当前要填的点的坐标,填了t个点,总共要填cnt个点,各行各列各九宫格填数情况。
可行性剪枝考虑:
发现一个有趣的性质:数独中每一行都会有1到9各出现一次,共有9行,所以1到9每个数到最后必定出现9次,所以可以设一个used[]数组记录数出现的次数,若小于0,肯定不是正解,回溯,故每次填空要用不仅usedi大于0且i在同行同列同九宫格都没有出现过的i。
最优性剪枝:
可以将所有空能填的最大的数*该空的分数求和得到一个还能得到的至多的分数zhiduo,填空时,若发现v+zhiduo还<=已搜到的答案ans,显然不会使答案更优,所以回溯;同时每填一个空都更新一下zhiduo,回溯时也要照顾到zhiduo。
AC代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm> using namespace std; int a[][],fen[][],cnt,zhiduo,m[][],ans;//第二下标: 0:纵坐标;1:横坐标 先纵再横
int ma[][],used[];
int h[],l[],maxh,maxl;//某行、列已经填了几个数 bool hang[][],lie[][],jiu[][][];//行、列、九宫格的填数情况 void init()
{
for(int i=;i<=;i++) used[i]=;
for(int f=;f<=;f++)//初始化每个空的分数,不懂的可以拿纸笔自己模拟一下
{
for(int i=f-;i<=-f+;i++) fen[f-][i]=fen[-f+][i]=f;
for(int j=f-+;j<=-f+-;j++) fen[j][f-]=fen[j][-f+]=f;
}
} void dfs(int k,int v,int x,int y)//要填第k个,当前分数v,当前填的空的纵、横坐标。
{
if(v+zhiduo<=ans) return;//最优性剪枝
for(int i=;i<=;i++)//填哪个数
{
if(used[i]&&(!hang[x][i])&&(!lie[y][i])&&(!jiu[x/][y/][i]))//可行性剪枝
{
v+=fen[x][y]*i;
if(k!=cnt)
{
used[i]--;
hang[x][i]=;lie[y][i]=;jiu[x/][y/][i]=;
h[x]++;l[y]++;
zhiduo-=fen[x][y]*ma[x][y];
maxh=maxl=;
a[x][y]=i;
for(int i=;i<=;i++) if(h[i]!=&&h[i]>h[maxh]) maxh=i;//找接下来要填的空
for(int i=;i<=;i++) if(!a[maxh][i]&&l[i]!=&&l[i]>l[maxl]) maxl=i;
dfs(k+,v,maxh,maxl);
hang[x][i]=;lie[y][i]=;jiu[x/][y/][i]=;//回溯的时候少一个都会wa啊
zhiduo+=fen[x][y]*ma[x][y];
h[x]--;l[y]--;
a[x][y]=;
used[i]++;
}
else
ans=max(ans,v);
v-=fen[x][y]*i;
}
}
} int main()
{
init();
int v=;
for(int i=;i<=;i++)
for(int j=;j<=;j++)
{
scanf("%d",&a[i][j]);
if(a[i][j])
{
used[a[i][j]]--;
h[i]++;
l[j]++;
if(hang[i][a[i][j]]||lie[j][a[i][j]]||jiu[i/][j/][a[i][j]])
{
cout<<-;
return ;
}
hang[i][a[i][j]]=;
lie[j][a[i][j]]=;
jiu[i/][j/][a[i][j]]=;
v+=fen[i][j]*a[i][j];
}
else
cnt++;
}
int most;
for(int i=;i<=;i++)//求起始时的至多zhiduo
for(int j=;j<=;j++)
if(!a[i][j])
{
most=;
while(hang[i][most]||lie[j][most]||jiu[i/][j/][most]) most--;
ma[i][j]=most;//空(j,i)能填的最大的数
zhiduo+=most*fen[i][j];
}
h[]=-;
l[]=-;
maxh=,maxl=;
for(int i=;i<=;i++)//找一开始要填的空
if(h[i]!=&&h[i]>h[maxh]) maxh=i;
for(int i=;i<=;i++)
if(!a[maxh][i]&&l[i]!=&&l[i]>l[maxl]) maxl=i;
dfs(,v,maxh,maxl);
if(!ans) ans=-;
cout<<ans;
return ;
}
一本通&&洛谷 ——靶型数独——题解的更多相关文章
- 洛谷P2832 行路难 分析+题解代码【玄学最短路】
洛谷P2832 行路难 分析+题解代码[玄学最短路] 题目背景: 小X来到了山区,领略山林之乐.在他乐以忘忧之时,他突然发现,开学迫在眉睫 题目描述: 山区有n座山.山之间有m条羊肠小道,每条连接两座 ...
- 【洛谷P3960】列队题解
[洛谷P3960]列队题解 题目链接 题意: Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有 n×m ...
- 洛谷P2312 解方程题解
洛谷P2312 解方程题解 题目描述 已知多项式方程: \[a_0+a_1x+a_2x^2+\cdots+a_nx^n=0\] 求这个方程在 \([1,m]\) 内的整数解(\(n\) 和 \(m\) ...
- 洛谷P1577 切绳子题解
洛谷P1577 切绳子题解 题目描述 有N条绳子,它们的长度分别为Li.如果从它们中切割出K条长度相同的 绳子,这K条绳子每条最长能有多长?答案保留到小数点后2位(直接舍掉2为后的小数). 输入输出格 ...
- 洛谷P2507 [SCOI2008]配对 题解(dp+贪心)
洛谷P2507 [SCOI2008]配对 题解(dp+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1299251 链接题目地址:洛谷P2507 [S ...
- 洛谷 P1220 关路灯 题解
Description 有 $n$ 盏路灯,每盏路灯有坐标(单位 $m$)和功率(单位 $J$).从第 $c$ 盏路灯开始,可以向左或向右关闭路灯.速度是 $1m/s$.求所有路灯的最少耗电.输入保证 ...
- 【洛谷P3410】拍照题解(最大权闭合子图总结)
题目描述 小B有n个下属,现小B要带着一些下属让别人拍照. 有m个人,每个人都愿意付给小B一定钱让n个人中的一些人进行合影.如果这一些人没带齐那么就不能拍照,小B也不会得到钱. 注意:带下属不是白带的 ...
- [BZOJ 3039&洛谷P4147]玉蟾宫 题解(单调栈)
[BZOJ 3039&洛谷P4147]玉蟾宫 Description 有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地. ...
- 洛谷P1074 靶形数独 [搜索]
题目传送门 题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z 博士拿出了 ...
随机推荐
- [DS+Algo] 010 二叉树的遍历
二叉树遍历 深度优先 一般用递归 一些名词 遍历方式 英文 先序 Preorder 中序 Inorder 后序 Postorder 广度优先 一般用队列 Python 代码示例 class Node( ...
- SQL Server之索引解析(二)
1.堆表 堆表通过IAM连接一起,查询时全表扫描. 1.1 非聚集索引 结构 叶子节点数据结构:行数据结构+Rid(8字节) 中间节点数据结构: (非聚集非唯一索引)行数据结构+Page(4)+2+ ...
- 【JZOJ 3910】Idiot 的间谍网络
题面: Description 作为一名高级特工,Idiot 苦心经营多年,终于在敌国建立起一张共有n 名特工的庞大间谍网络. 当然,出于保密性的要求,间谍网络中的每名特工最多只会有一名直接领导.现在 ...
- HNUSTOJ-1636 心电图
1636: 心电图 时间限制: 1 Sec 内存限制: 128 MB提交: 583 解决: 231[提交][状态][讨论版] 题目描述 众所周知,ACM/ICPC实验室聚集了一堆学霸Orz 有学霸 ...
- Rust学习笔记1
这是一份不错的rust教程,目前包括4个block和4个project.全部完成后可以用rust实现一个简单的key-value存储引擎. 注意:Windows下rust貌似会遇到一些bug,强烈建议 ...
- FreeIPA部署及基本使用
FreeIPA是一个集成安全信息管理解决方案,FreeIPA服务器通过存储管理计算机网络安全方面所需的用户.组.主机和其他对象的数据,提供集中的身份验证.授权和账户信息.结合了Linux.Direct ...
- django基础篇05-Form验证组件
Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 基本简单的操作: from django im ...
- fpga新建nios
[FPGA]基于Qsys的第一个Nios II系统设计 (2013-12-12 21:50:08) 转载▼ 标签: fpga niosii qsys helloword quartusii 分类: 嵌 ...
- boost::regex
https://blog.51cto.com/liam2199/2108548 正则表达式
- DDD领域驱动设计初探(四):WCF搭建
前言:前面三篇分享了下DDD里面的两个主要特性:聚合和仓储.领域层的搭建基本完成,当然还涉及到领域事件和领域服务的部分,后面再项目搭建的过程中慢慢引入,博主的思路是先将整个架构走通,然后一步一步来添加 ...