链接:

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(搜索, 剪枝)的更多相关文章

  1. [NOIP2009] 靶形数独(搜索+剪枝)

    题目描述 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他 们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教, Z 博士拿出了他最近发明的 ...

  2. Luogu P1074靶形数独【搜索/剪枝】By cellur925

    题目传送门 显然是一个搜索.但是开始没有任何的剪枝,暴力从\((1,1)\)点开始搜索,很自然地T了6个点. #include<cstdio> #include<algorithm& ...

  3. [ C语言版 ] 数独计算器 [ 搜索剪枝法 ]

    [原创]转载请注明出处. [浙江大学 程序设计专题] 使用方法:按提示输入方式为9*9的矩阵,0表示未知数. 为解决这一问题,我们也尝试了两种方法,准确的说,是第一种方法太慢了,我们对它进行了优化. ...

  4. NOIP2015 斗地主(搜索+剪枝)

    4325: NOIP2015 斗地主 Time Limit: 30 Sec  Memory Limit: 1024 MBSubmit: 270  Solved: 192[Submit][Status] ...

  5. hdu 5469 Antonidas(树的分治+字符串hashOR搜索+剪枝)

    题目链接:hdu 5469 Antonidas 题意: 给你一颗树,每个节点有一个字符,现在给你一个字符串S,问你是否能在树上找到两个节点u,v,使得u到v的最短路径构成的字符串恰好为S. 题解: 这 ...

  6. hdu 5887 搜索+剪枝

    Herbs Gathering Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  7. hdu 5113(2014北京—搜索+剪枝)

    题意:有N*M的棋盘,用K种颜色去染,要求相邻块不能同色.已知每种颜色要染的块数,问能不能染,如果能,输出任一种染法. 最开始dfs失败了- -,优先搜索一行,搜完后进入下一列,超时.本来以为搜索不行 ...

  8. luogu 1731 搜索剪枝好题

    搜索剪枝这个东西真的是骗分利器,然鹅我这方面菜的不行,所以搜索数学dp三方面是真的应该好好训练一下 一本通的确该认真的刷嗯 #include<bits/stdc++.h> using na ...

  9. 搜索+剪枝——POJ 1011 Sticks

    搜索+剪枝--POJ 1011 Sticks 博客分类: 算法 非常经典的搜索题目,第一次做还是暑假集训的时候,前天又把它翻了出来 本来是想找点手感的,不想在原先思路的基础上,竟把它做出来了而且还是0 ...

  10. [HNOI2002]彩票 (搜索+剪枝)

    题目描述 某地发行一套彩票.彩票上写有1到M这M个自然数.彩民可以在这M个数中任意选取N个不同的数打圈.每个彩民只能买一张彩票,不同的彩民的彩票上的选择不同. 每次抽奖将抽出两个自然数X和Y.如果某人 ...

随机推荐

  1. 批量导出docker images 的一个简单方法

    docker images |cut -c - |xargs docker save -o iamges.tar 主要 最大的长度不能超过 18 超过了就得改一下 -c 后面的数据长度 最终效果为: ...

  2. Hive_解析 get_json_object ( )

    Hive_解析 get_json_object ( )   get_json_object ( string json_string, string path ) 说明:  第一个参数填写json对象 ...

  3. csp模拟赛低级错误及反思

    \(csp\)模拟赛低级错误及反思. 1.没开\(longlong\). 反思:注意数据类型以及数据范围. 2.数组越界(前向星数组未开两倍,一题的数据范围应用到另一题上,要开两倍的写法为开两倍数组) ...

  4. 状压DP--Rotate Columns (hard version)-- Codeforces Round #584 - Dasha Code Championship - Elimination Round (rated, open for everyone, Div. 1 + Div. 2)

    题意:https://codeforc.es/problemset/problem/1209/E2 给你一个n(1-12)行m(1-2000)列的矩阵,每一列都可以上下循环移动(类似密码锁). 问你移 ...

  5. vue配置外放generate-asset-webpack-plugin

    解决方法:(共有2个方法) 1.借助插件  generate-asset-webpack-plugin .在webpack.prod.conf.js中去生成configServer.json文件,让其 ...

  6. Lua访问网页

    示例 例子,实现https方式,登录网站,访问某个网页,修改其中参数的功能.其中xx应用时候需要修改. require("curl") local ipList = { " ...

  7. How to enable remote connections to SQL Server

    <img src="https://miro.medium.com/max/1400/1*18lrHvJ8YtADJDT7hxIThA.jpeg" class="g ...

  8. QByteArray详解

    QByteArray在串口通讯中经常被使用,有一定必要较为全面详细的对QByteArray进行阐述.本文通过以下几个部分加以介绍: 1. 初始化 2. 访问与赋值 3. 添加.删除.插入与替换操作 4 ...

  9. wpf DrawingImage 奇葩问题

    使用wpf drawingImage绘图是,会出现很奇怪的坐标问题,这个问题困扰很久 当在DrawingGroup中绘图的时候,坐标始终会从(0,0)开始无论设置多少值,奇怪一比 解决方法:首先在Dr ...

  10. iptables防火墙操作-查看、配置、重启、关闭

    查看iptables端口配置 iptables -L -n --line-number iptables端口配置(不开通3389无法远程连接,不开通icmp无法ping) iptables -A IN ...