(1)最简单的最是去暴力DFS搜索答案 , 很容易想到 , 每行每列的方式去搜索 , 不过效率是真的不行;但这个还是给出代码 ,毕竟打了也不容易呀!

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=;
int map[maxn][maxn];
bool row[maxn][maxn];
bool col[maxn][maxn];
bool grid[maxn][maxn];
bool dfs(int r,int c)
{
if(r==) return true;//构造完毕
bool flag=false;
if(map[r][c])
{
if(c==) flag=dfs(r+,);
else flag=dfs(r,c+);
return flag;
}
int k=(r/)*+c/;
for(int i=;i<=;i++)if(!row[r][i]&&!col[c][i]&&!grid[k][i])
{
row[r][i]=col[c][i]=grid[k][i]=true;
map[r][c]=i;
if(c==) flag=dfs(r+,);
else flag=dfs(r,c+);
if(flag) return true;
map[r][c]=;
row[r][i]=col[c][i]=grid[k][i]=false;
}
return false;
}
int main()
{
int T; scanf("%d",&T);
while(T--)
{
memset(row,,sizeof(row));
memset(col,,sizeof(col));
memset(grid,,sizeof(grid));
for(int i=;i<;i++)
for(int j=;j<;j++)
{
char x;
scanf(" %c",&x);
map[i][j]= x-'';
if(map[i][j])
{
row[i][map[i][j]]=true;
col[j][map[i][j]]=true;
int k=(i/)*+j/;
grid[k][map[i][j]]=true;
}
}
dfs(,);
for(int i=;i<;i++)
{
for(int j=;j<;j++)
printf("%d",map[i][j]);
printf("\n");
}
}
return ;
}

(2)还有个更快的 ,就是利用舞蹈链(DLX)这种数据结构去快速实现这种问题 。(DLX:这里先给出模板,不先学习)

//******************************************************//
//输入T表示T组数据。 //
//每组数据为9个长度为9的字符串,空白处以字符0替代。 //
//POJ2676 //
//******************************************************// #include <bits/stdc++.h>
using namespace std;
const int maxnode = ;
const int MaxM = ;
const int MaxN = ;
struct DLX{
int n, m, size; //行数,列数,总数
int U[maxnode], D[maxnode], R[maxnode], L[maxnode], Row[maxnode], Col[maxnode];
int H[MaxN], S[MaxM]; //S记录该列剩余1的个数,H表示该行最左端的1
int ansd, ans[MaxN]; void init(int _n, int _m){
n = _n;
m = _m;
for(int i = ; i <= m; i++){
S[i] = ;
U[i] = D[i] = i;
L[i] = i-;
R[i] = i+;
}
R[m] = ; L[] = m;
size = m;
memset(H, -, sizeof(H));
}
void Link(int r, int c){
size++;
Col[size] = c, Row[size] = r;
S[c]++;
U[size] = U[c], D[size] = c;
D[U[c]] = size;
U[c] = size;
if (H[r] != -) {
R[size] = H[r] ;
L[size] = L[H[r]] ;
R[L[size]] = size ;
L[R[size]] = size ;
}
else
H[r] = L[size] = R[size] = size ;
}
void remove(int c){//覆盖第c列。删除第c列及能覆盖到该列的行,防止重叠
L[R[c]] = L[c]; R[L[c]] = R[c];
for(int i = D[c]; i != c; i = D[i])
for(int j = R[i]; j != i; j = R[j]){
U[D[j]] = U[j];
D[U[j]] = D[j];
--S[Col[j]];
}
}
void resume(int c){
for(int i = U[c]; i != c; i = U[i])
for(int j = L[i]; j != i; j = L[j]){
++ S[Col[j]];
U[D[j]] = j;
D[U[j]] = j;
}
L[R[c]] = R[L[c]] = c;
}
//d为递归深度
bool dance(int d){
if(R[] == ){
ansd = d;
return true;
}
int c = R[];
for(int i = R[]; i != ; i = R[i])
if(S[i] < S[c])
c = i;
remove(c);
for(int i = D[c];i != c;i = D[i]){
ans[d] = Row[i];
for(int j = R[i]; j != i; j = R[j]) remove(Col[j]);
if(dance(d+)) return true;
for(int j = L[i]; j != i; j = L[j]) resume(Col[j]);
}
resume(c);
return false;
}
};
DLX g;
char s[][];
int main(){
int t;
scanf("%d", &t);
while(t--){
for(int i = ; i < ; i++)
scanf("%s", s[i]); g.init(*, +++); for(int i = ; i < ; i++)
for(int j = ; j < ; j++){
int x = i, y = j, z = x/*+y/, w = i*+j;
if(s[i][j] == ''){
for(int k = ; k <= ; k++){
g.Link(w*+k, w+);
g.Link(w*+k, +x*+k);
g.Link(w*+k, +y*+k);
g.Link(w*+k, +z*+k);
}
}
else {
int t = s[i][j]-'';
g.Link(w*+t, w+);
g.Link(w*+t, +x*+t);
g.Link(w*+t, +y*+t);
g.Link(w*+t, +z*+t);
}
}
g.dance(); for(int i = ; i < g.ansd; i++){
int t = g.ans[i];
int a = (t-)/, b = (t-)%+'';
s[a/][a%] = b;
}
for(int i = ; i < ; i++)
puts(s[i]);
}
return ;
}

(3) 还有就是重要需要讲解的状态搜索:

1、答案

状态:我们关心数独每个位置填了什么数。我们需要在每个状态中找出没有填的位置,检查有哪些值可以填。这些可以填的值构成了向下递归的分支。(状态就是每个每个时刻的9*9数独)
搜索边界:1、所有位置填完了,找到答案。2、发现某个位置没有能填的值,搜索失败。
提醒:对于每个状态下,我们要找的是1个位置填什么,而不是枚举所有位置和能填的数(其他位置会在更深的地方被搜索到)。
2、剪枝

优化搜索顺序:如果是人类玩数独,策略一定是先填上“已经能够唯一确定的位置”,考虑在该位置填什么数,再向下搜索。所以我们在每个状态下选择所有未填的位置中,能填合法数字最少的位置,考虑在这上面填数。
3、位运算

对于每行,每列,每个九宫格,分别用一个9为二进制数保存哪些数字还可以填。
对于每个位置,把他锁在的行,列,九宫格对应的数取 & 运算就可以得到剩余哪些数可以填。lowbit(x)取出能填的数。
当某个位置的数填上时把对应的行,列,九宫格对应位置改为0。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std; char str[][];
int row[], col[], grid[], cnt[], num[], tot;
int g(int x, int y){
return ((x / ) * ) + (y / );//在第几个九宫格
}
void flip(int x, int y, int z){
row[x] ^= <<z; //x行z不能填了
col[y] ^= <<z;
grid[g(x,y)] ^= <<z;
} bool dfs(int now){//剩余要填的数的总数
if(now == )return ;
//优化顺序:枚举每个位置,找能填的最少的填
int t = , x, y;
for(int i = ; i < ; i++){
for(int j = ; j < ; j++){
if(str[i][j] != '')continue;
int val = row[i] & col[j] & grid[g(i,j)];
if(!val)return ;
if(cnt[val] < t){///查看那个小宫格填入好
t = cnt[val];
x = i, y = j;
}
}
}
//填数
int val = row[x] & col[y] & grid[g(x,y)];
for(; val; val -= val&-val){
int z = num[val&-val];//能填的数
str[x][y] = ''+z;
flip(x,y,z);
if(dfs(now-))return ;
flip(x,y,z);
str[x][y] = '';
}
return ;
} int main(){
//每个状态已经填的数有几个
for(int i = ; i < <<; i++)
for(int j = i; j; j-=j&-j)cnt[i]++;
//对于状态(1<<i),对应的数为'1'+num[1<<i];
for(int i = ; i < ; i++)
num[<<i] = i;
int T; cin>>T;
while(T--){
//data in
for(int i = ; i < ; i++)scanf("%s",str[i]);
//初始化,都可以填。
for(int i = ; i < ; i++)row[i] = col[i] = grid[i] = (<<)-;
tot = ;
//
for(int i = ; i < ; i++)
for(int j = ; j < ; j++)
if(str[i][j] != '')flip(i,j,str[i][j]-'');
else tot++;
dfs(tot);
//data out
cout<<'\n';
for(int i = ; i < ; i++)
printf("%s\n",str[i]);
}
return ;
}

POJ2676 (数独问题 + DLX + 状态优化顺序)的更多相关文章

  1. 任务二:1、选择器 2、连接集中状态的顺序 3、浮动的用发和原理 4、盒模型在IE和Google等不同浏览器的区别与联系

    1.选择器类型 标签选择器,类选择器,ID选择器,组合选择器,伪类和伪元素,属性选择器,子选择器,同胞选择器, :not()选择器 1.同胞选择器 相邻同胞标签: h2 + p{ color:red; ...

  2. Oracle性能优化顺序表名称来选择最有效的学习笔记

    选择最有效的顺序表名(只有有效的基于规则的优化)  ORACLE分析器按照订单处理从右到左FROM在FROM子句中的表名,故FROM写在最后的表(基础表 driving table)将被最先处理. 在 ...

  3. NOIP 2009 靶形数独(DLX)

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

  4. [NOIP2009]靶形数独 深搜+枝杈优化

    这道题,又是一位玄学搜索...... 我是用的蜗牛序搜的(顾名思义,@,这么搜),我正着搜80然后一反转比原来快了几十倍........一下AC....... 我的思路是这样的话我们可以从内到外或者从 ...

  5. CSS链接四种状态注意顺序、UI伪类选择器的顺序

    css定义超链接是要有先后顺序的.否则,可能会出现某个或某几个样式不起作用的bug.例如:visited与hover顺序颠倒了,则不能显示hover和active的样式了. 正确的顺序: a:link ...

  6. [C1] C1ComboBox 的非编辑状态优化

    一.前言 先看看 WPF 自带的 ComboBox 在非编辑状态,自定义 ItemTemplate 的情况下,效果如下图所示: 其当前选中的项(红框内)与自定义的 ItemTemplate 一样: 但 ...

  7. 根据 MySQL 状态优化 ---- 4. 临时表

    查看 MySQL 服务器运行的各种状态值: mysql> show global status: 4. 临时表 查看设置: mysql> show variables where Vari ...

  8. 根据 MySQL 状态优化 ---- 1. 慢查询

    查看 MySQL 服务器运行的各种状态值: mysql> show global status: 1. 慢查询 mysql> show variables like '%slow%'; + ...

  9. Mysql 【影响性能的几个方面】以及【性能优化顺序】

    服务器性能   cpu  可用内存大小  网络   IO (增加IO子系统) mysql 存储引擎 数据库服务器配置参数(主要优化方向)     数据库结构设计,sql语句.   慢查询

随机推荐

  1. Windows10更新后无限重启

    以安全模式进入系统,禁用或卸载显卡驱动. 重启后重新安装驱动.

  2. re.spilt

  3. 关于android写入SD卡数据的学习代码

    String path = "data/data/com.example.qqlogin/login.txt"; FileOutputStream fos = new FileOu ...

  4. day69-oracle 22-DBCA

    只涉及到数据库的管理,不涉及到数据库的开发.不涉及到写SQL程序或者是写增删改查,不涉及到这些东西,也不涉及到事务. 你在安装oracle的时候它自动帮你创建一个数据库.

  5. 05 HTML字符串转换成jQuery对象、绑定数据到元素上

    1 要求 将一段 HTML脚本 封装成一个字符串,将这个字符串转换成一个jQuery对象:然后将这个jQuery对象添加到指定的元素中去 2 步骤 定义字符串 var str = '<div i ...

  6. java全栈day33--html

    本天要完成6个任务,并且布局静态页面(首页)详细分为六个部分  如下 网站信息页面案例(字体标签.排版标签) 网站图片信息页面案例(图片标签) 网站友情链接页面案例(列表标签) 网站首页案例(表格标签 ...

  7. C++面试笔记--面向对象

    说到面向对象,大家第一反应应该就是它的三大特性:封装性.继承性和多态性.那么我们先简单的了解一下这三大特性: (1)封装性:封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的 ...

  8. Windows系统编程之进程同步试验

    试验过程中调用了不少系统函数,并且涉及到一些系统级的概念,在此记录下来做为解决问题的一种方式.也许在以后的编程的过程中是否可以通过调用系统平台上的东西来完成一些任务,这仍不失为一种好的思维方式. 多线 ...

  9. 国内物联网平台(7):Ablecloud物联网自助开发和大数据云平台

    国内物联网平台(7)——Ablecloud物联网自助开发和大数据云平台 马智 平台定位 面向IoT硬件厂商,提供设备联网与管理.远程查看控制.定制化云端功能开发.海量硬件数据存储与分析等基础设施,加速 ...

  10. Vistual Studio的导出模板功能

    应用场景,每个项目有自己固定的目录结构和引用文件, 无需每次创建一个项目,就手工一一将那些目录再new一遍.如图所示 菜单  文件=>导出模板 之后的操作基本上一路"下一步" ...