传送门

这道题是很好的一道IDA*练习题。

首先我们先确定搜索的框架,我们要求的是用最少的修改次数使得所有的行,列,宫之内都有偶数个1,最直观的想法显然是先预处理出有奇数个1的行,列,宫,之后枚举每一个点,如果这个点在奇数个1的行/列/宫之中就开始修改,继续搜索。修改整个数独之后判定,回溯。

这个正确性是没问题的,但是你难以通过有效的手段减少搜索树大小(比如从1多的开始搜?),这样肯定会超时(想想靶型数独)。

于是我们引入新的操作:ID(迭代加深)搜索!

ID的原理是,有可能搜索树某些分枝非常的深,但里面并没有你要的解,如果你率先进入的话,就会浪费大量的时间在里面。有可能解的深度并不是很大,所以我们可以每次设定一个搜索的深度,如果超过这个深度就返回,之后继续加大深度搜索,所以叫迭代加深。

但是这样我们依然可能很慢,所以我们再加上一个,A*算法!

A*算法简单来说,就是设计一个估价函数,估计未来的搜索情况,选择当前估计最好的一个搜索方向去搜索。估计的值越接近实际值,搜索效率越高。估价函数有一个原则,就是估计的值不可以大于实际值,否则就会导致得到错误的答案。(因为估计值过大掩盖了真实的解)而且我们无需担心正确性,因为A*算法只是优先进入分支,在进行一段时间搜索之后,原来被忽略的分支又将进入计算。A*的估价函数如果一直是0,那么他就相当于是一个无优化的搜索,所以说A*算法的效率一般来讲是高于普通搜索的,至于高多少就要看设计的估价函数的高明之处了。

A*的实现比较复杂,但与ID结合起来成为IDA*就比较好实现了,它其实可以被视为剪枝,当当前的值加上估价值比当前的最大深度更大,就直接返回,相当于剪枝了。在这道题中,我们要做的就是从小到大枚举搜索深度(就是修改的次数),在每次设计一个估价函数,根据上面的原则,我们修改之后,至多需要max有奇数个1的(行,列,宫)次修改,每次估价函数设为三者最大值即可。

这样搜索快到飞起,也有可能是本题数据比较水……

看一下代码。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<set>
#include<queue>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n') using namespace std;
typedef long long ll;
const int M = ;
const int INF = ; int read()
{
int ans = ,op = ;
char ch = getchar();
while(ch < '' || ch > '')
{
if(ch == '-') op = -;
ch = getchar();
}
while(ch >= '' && ch <= '')
{
ans *= ;
ans += ch - '';
ch = getchar();
}
return ans * op;
} int b,c,r,row[],col[],blo[],maxd;
char s[]; int B(int x,int y)
{
return ((x - ) / * + (y - ) / ) + ;
} int h()
{
return max(r,max(b,c));
} int cal(int x)
{
return (!x) ? - : ;
} void change(int i,int j)
{
row[i] ^= ,col[j] ^= ,blo[B(i,j)] ^= ;
r += cal(row[i]),c += cal(col[j]),b += cal(blo[B(i,j)]);
} void dfs(int x,int y,int d)
{
if(d > maxd) return;
if(x == && y == )
{
rep(i,,) if(row[i] | col[i] | blo[i]) return;
printf("%d\n",maxd),exit();
}
if(row[x] | col[y] | blo[B(x,y)])
{
change(x,y);
if(d + + h() <= maxd) (y == ) ? dfs(x+,,d+) : dfs(x,y+,d+);
change(x,y);
if(d + h() <= maxd) (y == ) ? dfs(x+,,d) : dfs(x,y+,d);
}
else (y == ) ? dfs(x+,,d) : dfs(x,y+,d);
} int main()
{
rep(i,,)
{
scanf("%s",s+);
rep(j,,) if(s[j] == '') change(i,j);
}
for(maxd = ;;maxd++) dfs(,,);
return ;
}

[USACO11NOV]二进制数独Binary Sudoku的更多相关文章

  1. P3032 [USACO11NOV]二进制数独Binary Sudoku

    题目描述 Farmer John's cows like to play an interesting variant of the popular game of "Sudoku" ...

  2. 2016年11月3日JS脚本简介数据类型: 1.整型:int 2.小数类型: float(单精度) double(双精度) decimal () 3.字符类型: chr 4.字符串类型:sting 5.日期时间:datetime 6.布尔型数据:bool 7.对象类型:object 8.二进制:binary 语言类型: 1.强类型语言:c++ c c# java 2.弱类型语

    数据类型: 1.整型:int 2.小数类型: float(单精度) double(双精度) decimal () 3.字符类型: chr 4.字符串类型:sting 5.日期时间:datetime 6 ...

  3. MySQL 二进制日志(Binary Log)

    同大多数关系型数据库一样,日志文件是MySQL数据库的重要组成部分. MySQL有几种不同的日志文件.通常包括错误日志文件,二进制日志,通用日志,慢查询日志,等等.这些日志能够帮助我们定位mysqld ...

  4. [逆向工程] 二进制拆弹Binary Bombs 快乐拆弹 详解

    二进制拆弹 binary bombs 教你最快速解题,成功拆弹 最近计算机基础课,的实验lab2,二进制拆弹,可以说是拆的我很快乐了(sub n, %hair) 此处头发减n 我刚开始做的时候很是懵逼 ...

  5. Leetcode之回溯法专题-37. 解数独(Sudoku Solver)

    Leetcode之回溯法专题-37. 解数独(Sudoku Solver) 编写一个程序,通过已填充的空格来解决数独问题. 一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次.数字 1 ...

  6. 二进制日志BINARY LOG清理

    mysql> show master logs; +------------------+-----------+ | Log_name | File_size | +------------- ...

  7. Arduino 串口篇 Arduino发送二进制 send binary via RS232-to-USB to PC

    有用的链接在这里:http://hi.baidu.com/mizuda/item/06b7fdc1d0e45a0ec710b2dd 更加详细的内容请查阅Arduino官方:http://arduino ...

  8. 求解数独难题, Sudoku问题(回溯)

    Introduction : 标准的数独游戏是在一个 9 X 9 的棋盘上填写 1 – 9 这 9 个数字,规则是这样的: 棋盘分成上图所示的 9 个区域(不同颜色做背景标出,每个区域是 3 X 3 ...

  9. [Swift]LeetCode36. 有效的数独 | Valid Sudoku

    Determine if a 9x9 Sudoku board is valid. Only the filled cells need to be validated according to th ...

随机推荐

  1. memcached安装与初步

    mac 首先安装homebrew 根目录下 /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew ...

  2. vueSSR渲染原理

    优点:利于搜索引擎,解决白屏问题,因为正常情况下在index.html文件中只有一个简单的标签,没有内容,不利于爬虫搜索 场景:交互少,数据多,例如新闻,博客,论坛类等 原理:相当于服务端前面加了一层 ...

  3. Nuxt.js使用mint-ui

    环境 vue nuxt 要使用mint-ui 记录下其中的坑 npm install mint-ui --save plugins目录下 增加 mint-ui.js 代码: import Vue fr ...

  4. 将一个文件从gbk编码转换为utf8编码

    用django展示模板时,出现如下错误: 'utf8' codec can't decode byte 0xd3 in position 197: invalid continuation byte ...

  5. UVA - 11178-Morley’s Theorem

    就是给出一个等边三角形的三个顶点坐标 然后每一个角的三等分线会交错成一个三角形,求出这个三角形的顶点坐标 一開始.我题意理解错了--还以为是随意三角形,所以代码可以处理随意三角形的情况 我的做法: 通 ...

  6. js中有包装类,java中也有包装类

    new Number() vs Number() What is the difference between new Number() and Number()? I get that new Nu ...

  7. 如何推断一个P2P平台是否靠谱?

    推断一个站点,是否靠谱.是有规律可循的.P2P平台算是个新兴的电商类站点.   网上欺诈类的站点.不限于P2P,实在是太多了,真的有必要总结下最关键的几个靠谱指标.   最关键的2个   1.创始人和 ...

  8. Qt、C++ 简易计算器

    Qt.C++实现简易计算器: 以下内容是我实现这个简易计算器整个过程,其中包括我对如何实现这个功能的思考.中途遇到的问题.走过的弯路 整个实现从易到难,计算器功能从简单到复杂,最开始设计的整个实现步骤 ...

  9. AliYunDun关闭

    停止阿里云盾AliYunDun服务解决大量写磁盘问题-小内存ECS服务器 阿里云数据库在没备案,涉及大量IO操作时会自动启动阿里云盾这个服务,会导致服务器变得很卡 关闭服务: service aegi ...

  10. run as maven test报错解决办法

    eclipse中使用maven插件的时候,运行run as maven build的时候报错 -Dmaven.multiModuleProjectDirectory system propery is ...