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.如果某人 ...
随机推荐
- Mac下安装SecureCRT客户端并激活
1. 先下载SecureCRT和破解文件 默认下载到了当前用户的”下载”目录中 2. 在”Finder”中 打开 “scrt-7.3.0-657.osx_x64.dmg” 并将 SecureCRT复制 ...
- (5.3.2)数据库迁移——SSIS包批量导出
SSIS连接出错 原因 : ssms 工具 不是 admin 权限 打开的 SSIS包批量导出代码 use msdb go IF OBJECT_ID('msdb.dbo.usp_ExportS ...
- delphi 相关好的资料网站
1.Delphi编程技巧大全 http://www.delphitop.com/ (实例讲解所有组件) 2.Delphi学习大师 Delphi基础教程 视频教程 http://www.xue ...
- django 聚合统计查询
from django.shortcuts import renderfrom django.http import HttpResponsefrom django.db.models import ...
- python-day7(正式学习)
目录 数字类型内置方法 整形内置方法(int) 常用操作+内置方法 是否可变 浮点型内置方法(float) 常用操作+内置方法 是否可变 字符串内置方法 常用操作+内置方法 是否可变 数字类型内置方法 ...
- C/S软件方案
互联网时代客户端软件的一些方案 纯Native开发, C++/C#/duilib+C++(Windows), Objective-c(Mac) Qt(Windows/Mac) NW.js/Electr ...
- Boot-crm管理系统开发教程(总结)
这个Boot-crm管理系统我花了大概两周写完,因为是刚学完SSM框架,所以立马开始了这个项目,项目初期,运行书本上给的前端代码都报了许多错误,导致这个原因是因为书本给的 设计说明文档 没有看清楚.然 ...
- 22-Perl Socket 编程
1.Perl Socket 编程Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯. ...
- JS基础_条件运算符
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- [转载]深入理解maven构建生命周期和各种plugin插件
我就不复制博主文章了,到原文地址看吧.写这个只是为了自己搜索起来方便些: https://blog.csdn.net/zhaojianting/article/details/80321488 htt ...