Acwing-169-数独2(搜索, 剪枝)
链接:
https://www.acwing.com/problem/content/171/
题意:
请你将一个16x16的数独填写完整,使得每行、每列、每个4x4十六宫格内字母A~P均恰好出现一次。
保证每个输入只有唯一解决方案。
思路:
每个坐标维护一个16位的数, 用来记录某个值是否使用.
对每个位置, 如果只能填一个,则直接填, 对空格如果不能填, 则返回.
对每一行, 只能在一个位置使用的值直接填, 同时一行不能覆盖a-p,则返回,
列, 块同理.
再从所有可行位置,找到一个可填值最少的开始枚举.
还要多开数组记录状态, 方便复原.
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 16;
char Map[N][N+1];
char TmpMap[N*N+1][N][N+1];
int State[N][N];
int TmpS1[N*N+1][N][N], TmpS2[N*N+1][N][N];
int Num[1<<N], Cnt[1<<N];
int cnt;
int Lowbit(int x)
{
return x&(-x);
}
void Change(int x, int y, int p)
{
Map[x][y] = 'A'+p;
for (int i = 0;i < N;i++)
{
State[x][i] &= ~(1<<p);
State[i][y] &= ~(1<<p);
}
int sx = (x/4)*4, sy = (y/4)*4;
for (int i = 0;i < 4;i++)
{
for (int j = 0;j < 4;j++)
State[sx+i][sy+j] &= ~(1<<p);
}
State[x][y] = 1<<p;
}
bool Dfs(int step)
{
if (step == 0)
return true;
int tmpcnt = step;
memcpy(TmpS1[tmpcnt], State, sizeof State);
memcpy(TmpMap[tmpcnt], Map, sizeof Map);
//保存副本
//处理每个空格
for (int i = 0;i < N;i++)
{
for (int j = 0;j < N;j++)
{
if (Map[i][j] == '-')
{
if (State[i][j] == 0)
{
memcpy(State, TmpS1[tmpcnt], sizeof State);
memcpy(Map, TmpMap[tmpcnt], sizeof Map);
return false;
}
if (Cnt[State[i][j]] == 1)
{
Change(i, j, Num[State[i][j]]);
step--;
}
}
}
}
//处理每一行
for (int i = 0;i < N;i++)
{
int all = 0, use = (1<<N)-1;
int used = 0;
for (int j = 0;j < N;j++)
{
int s = State[i][j];
use &= ~(all & s);//记录只在一个位置出现过的点
all |= s;//记录全集
if (Map[i][j] != '-')
used |= State[i][j];//记录放置的点
}
if (all != (1<<N)-1)
{
memcpy(State, TmpS1[tmpcnt], sizeof State);
memcpy(Map, TmpMap[tmpcnt], sizeof Map);
return false;
}
for (int j = use;j > 0;j -= Lowbit(j))
{
int t = Lowbit(j);
if (!(used & t))
{
for (int k = 0;k < N;k++)
{
if (State[i][k] & t)
{
Change(i, k, Num[t]);
--step;
break;
}
}
}
}
}
//处理每一列
for (int i = 0;i < N;i++)
{
int all = 0, use = (1<<N)-1;
int used = 0;
for (int j = 0;j < N;j++)
{
int s = State[j][i];
use &= ~(all & s);
all |= s;
if (Map[j][i] != '-')
used |= State[j][i];
}
if (all != (1<<N)-1)
{
memcpy(State, TmpS1[tmpcnt], sizeof State);
memcpy(Map, TmpMap[tmpcnt], sizeof Map);
return false;
}
for (int j = use;j > 0;j -= Lowbit(j))
{
int t = Lowbit(j);
if (!(used & t))
{
for (int k = 0;k < N;k++)
{
if (State[k][i] & t)
{
Change(k, i, Num[t]);
--step;
break;
}
}
}
}
}
//处理每一个区块
for (int i = 0;i < N;i++)
{
int all = 0, use = (1<<N)-1;
int used = 0;
for (int j = 0;j < N;j++)
{
int sx = i/4*4, sy = i%4*4;
int dx = j/4, dy = j%4;
int s = State[sx+dx][sy+dy];
use &= ~(all & s);
all |= s;
if (Map[sx+dx][sy+dy] != '-')
used |= State[sx+dx][sy+dy];
}
if (all != (1<<N)-1)
{
memcpy(State, TmpS1[tmpcnt], sizeof State);
memcpy(Map, TmpMap[tmpcnt], sizeof Map);
return false;
}
for (int j = use;j > 0;j -= Lowbit(j))
{
int t = Lowbit(j);
if (!(used & t))
{
for (int k = 0;k < N;k++)
{
int sx = i/4*4, sy = i%4*4;
int dx = k/4, dy = k%4;
if (State[sx+dx][sy+dy] & t)
{
Change(sx+dx, sy+dy, Num[t]);
--step;
break;
}
}
}
}
}
// cout << step << endl;
if (step == 0)
return true;
int x, y, s = 100;
for (int i = 0;i < N;i++)
{
for (int j = 0;j < N;j++)
{
if (Map[i][j] == '-' && Cnt[State[i][j]] < s)
{
s = Cnt[State[i][j]];
x = i, y = j;
}
}
}
memcpy(TmpS2[tmpcnt], State, sizeof State);
for (int i = State[x][y];i > 0;i -= Lowbit(i))
{
memcpy(State, TmpS2[tmpcnt], sizeof State);
Change(x, y, Num[Lowbit(i)]);
if (Dfs(step-1))
return true;
}
memcpy(State, TmpS1[tmpcnt], sizeof State);
memcpy(Map, TmpMap[tmpcnt], sizeof Map);
return false;
}
int main()
{
for (int i = 0;i < N;i++)
Num[1<<i] = i;
for (int i = 0;i < (1<<N);i++)
{
for (int j = i;j > 0;j -= Lowbit(j))
Cnt[i]++;
}
while (cin >> Map[0])
{
for (int i = 1;i < N;i++)
cin >> Map[i];
for (int i = 0;i < N;i++)
{
for (int j = 0;j < N;j++)
State[i][j] = (1<<N)-1;
}
cnt = 0;
for (int i = 0;i < N;i++)
{
for (int j = 0;j < N;j++)
{
if (Map[i][j] != '-')
Change(i, j, Map[i][j]-'A');
else
cnt++;
}
}
Dfs(cnt);
for (int i = 0;i < N;i++)
puts(Map[i]);
puts("");
}
return 0;
}
Acwing-169-数独2(搜索, 剪枝)的更多相关文章
- [NOIP2009] 靶形数独(搜索+剪枝)
题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z 博士拿出了他最近发明的 ...
- Luogu P1074靶形数独【搜索/剪枝】By cellur925
题目传送门 显然是一个搜索.但是开始没有任何的剪枝,暴力从\((1,1)\)点开始搜索,很自然地T了6个点. #include<cstdio> #include<algorithm& ...
- [ C语言版 ] 数独计算器 [ 搜索剪枝法 ]
[原创]转载请注明出处. [浙江大学 程序设计专题] 使用方法:按提示输入方式为9*9的矩阵,0表示未知数. 为解决这一问题,我们也尝试了两种方法,准确的说,是第一种方法太慢了,我们对它进行了优化. ...
- NOIP2015 斗地主(搜索+剪枝)
4325: NOIP2015 斗地主 Time Limit: 30 Sec Memory Limit: 1024 MBSubmit: 270 Solved: 192[Submit][Status] ...
- hdu 5469 Antonidas(树的分治+字符串hashOR搜索+剪枝)
题目链接:hdu 5469 Antonidas 题意: 给你一颗树,每个节点有一个字符,现在给你一个字符串S,问你是否能在树上找到两个节点u,v,使得u到v的最短路径构成的字符串恰好为S. 题解: 这 ...
- hdu 5887 搜索+剪枝
Herbs Gathering Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- hdu 5113(2014北京—搜索+剪枝)
题意:有N*M的棋盘,用K种颜色去染,要求相邻块不能同色.已知每种颜色要染的块数,问能不能染,如果能,输出任一种染法. 最开始dfs失败了- -,优先搜索一行,搜完后进入下一列,超时.本来以为搜索不行 ...
- luogu 1731 搜索剪枝好题
搜索剪枝这个东西真的是骗分利器,然鹅我这方面菜的不行,所以搜索数学dp三方面是真的应该好好训练一下 一本通的确该认真的刷嗯 #include<bits/stdc++.h> using na ...
- 搜索+剪枝——POJ 1011 Sticks
搜索+剪枝--POJ 1011 Sticks 博客分类: 算法 非常经典的搜索题目,第一次做还是暑假集训的时候,前天又把它翻了出来 本来是想找点手感的,不想在原先思路的基础上,竟把它做出来了而且还是0 ...
- [HNOI2002]彩票 (搜索+剪枝)
题目描述 某地发行一套彩票.彩票上写有1到M这M个自然数.彩民可以在这M个数中任意选取N个不同的数打圈.每个彩民只能买一张彩票,不同的彩民的彩票上的选择不同. 每次抽奖将抽出两个自然数X和Y.如果某人 ...
随机推荐
- java23种设计模式之五:代理模式
一.代理模式介绍 代理模式的定义:就是为一个接品(对象)提供一个代理的对象,并由这个代理对象控制对原对象的访问流程 其中代理又分为:静态代理和动态代理 静态代理:指的是自己要写一个代理类,或者用工具生 ...
- 利用PLSQL Developer对oracle中的数据进行备份恢复
--以备份scott用户为例,目标(备份里面所有的对象)--切换到scottconn scott/tiger;--进入 工具-->导出用户对象 如图所示 创建表空间及用户名,并赋予权限 -- ...
- Redis客户端相关
1.redis是什么 redis是一个开源的.使用C语言编写的.支持网络交互的.可基于内存也可持久化的Key-Value数据库.redis的官网地址,非常好记,是redis.io.目前,Vmware在 ...
- RESTful、共用接口、前后端分离、接口约定的实践 (转)
出处: 某小公司RESTful.共用接口.前后端分离.接口约定的实践 前言 随着互联网高速发展,公司对项目开发周期不断缩短,我们面对各种需求,使用原有对接方式,各端已经很难快速应对各种需求,更难以提 ...
- springboot打包的jar项目,不需要安装jdk环境启动
因为服务器上是JDK7,而springboot至少用JDK8才行,但是又因为是很老的项目,不是很清楚能不能换JDK8,有风险,因此选择以前项目用JDK7,而新的springboot用JDK8.步骤一: ...
- 日历控件datetimepicker(IE11)
1.安装 smalot.bootstrap-datetimepicker 2.引用 bootstrap.css bootstrap-datetimepicker.min.css jquery-1.10 ...
- js获取图片信息
网络图片: fetch(item.path).then(function(res){ // 计算图片大小 return res.blob() }).then(function(data){ conso ...
- vuejs 深度监听
data: { obj: { a: 123 } }, 监听obj中a属性 watch: { 'obj.a': { handler(newName, oldName) { console.log('ob ...
- API工具下载地址记录一下
java 1.6 帮助文档中文链接:http://download.csdn.net/detail/qw599186875/9608735 中文 – 谷歌版在线版: https://blog.fond ...
- 第六章·Logstash深入-收集java日志
1.通过Logstash收集java日志并输出到ES中 因为我们现在需要用Logstash收集tomcat日志,所以我们暂时将tomcat安装到Logstash所在机器,也就是db03:10.0.0. ...