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.如果某人 ...
随机推荐
- [bzoj2597][Wc2007]剪刀石头布_费用流
[Wc2007]剪刀石头布 题目大意:https://www.lydsy.com/JudgeOnline/problem.php?id=2597 题解: 发现直接求三元环不好求,我们考虑任选三个点不是 ...
- [转帖]postgresql 在等待服务器启动时超时
postgresql 在等待服务器启动时超时 2018年12月24日 :: my_name_nb 阅读数 版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接 ...
- 在Docker Container 内部安装 Mono 的方法 ---From官网
1.首先 mono 是什么 Mono是一个由Xamarin公司(先前是Novell,最早为Ximian)所主持的自由开放源代码项目. 该项目的目标是创建一系列匹配ECMA标准(Ecma-334和Ecm ...
- idea的配置文件------application.properties和application.yml
当application.yml 和 application.properties 两个文件同时存在的时候,application.properties的优先级是高于application.yml的, ...
- 怎样使用 Vue 的监听属性 watch ?
需求: 我需要在某个数据变化时能够执行特定的动作, 比如我在输入框中输入数字 88, 系统检测到以后就会弹窗 拜拜 , 而输入其他字符则不会触发, 这种需求简直多入牛毛, 实际上这就是 自定义事件 , ...
- 12-Perl 时间日期
1.Perl 时间日期本章节介绍 Perl 语言对时间日期的处理.Perl中处理时间的函数有如下几种: time() 函数:返回从1970年1月1日起累计的秒数 localtime() 函数:获取本地 ...
- c# 后台隐式使用webBrowser
c#不使用 webBrowser 控件, 在后台加载html流 private void button1_Click(object sender, EventArgs e) { string urlP ...
- [转载]Pytorch中nn.Linear module的理解
[转载]Pytorch中nn.Linear module的理解 本文转载并援引全文纯粹是为了构建和分类自己的知识,方便自己未来的查找,没啥其他意思. 这个模块要实现的公式是:y=xAT+*b 来源:h ...
- 嵌套For循环性能优化
请对以下的代码进行优化 for (int i = 0; i < 1000; i++) for (int j = 0; j < 100; j++) for (int k = 0; k < ...
- ztree树id、pid转成children格式的(待整理完整)
山铝菜单 因为菜单选用了bootstrap treeview ,而格式需要是children类似的格式 var nodes = [ {name: "父节点1", children: ...