POJ 2676 Sudoku (DFS)
| Time Limit: 2000MS | Memory Limit: 65536K | |||
| Total Submissions: 11694 | Accepted: 5812 | Special Judge | ||
Description

Input
Output
Sample Input
1
103000509
002109400
000704000
300502006
060000050
700803004
000401000
009205800
804000107
Sample Output
143628579
572139468
986754231
391542786
468917352
725863914
237481695
619275843
854396127
Source
大致题意:
九宫格问题,也有人叫数独问题
把一个9行9列的网格,再细分为9个3*3的子网格,要求每行、每列、每个子网格内都只能使用一次1~9中的一个数字,即每行、每列、每个子网格内都不允许出现相同的数字。
0是待填位置,其他均为已填入的数字。
要求填完九宫格并输出(如果有多种结果,则只需输出其中一种)
如果给定的九宫格无法按要求填出来,则输出原来所输入的未填的九宫格
解题思路:
DFS试探,失败则回溯
用三个数组进行标记每行、每列、每个子网格已用的数字,用于剪枝
bool row[10][10]; //row[i][x] 标记在第i行中数字x是否出现了
bool col[10][10]; //col[j][y] 标记在第j列中数字y是否出现了
bool grid[10][10]; //grid[k][x] 标记在第k个3*3子格中数字z是否出现了
row 和 col的标记比较好处理,关键是找出grid子网格的序号与 行i列j的关系
即要知道第i行j列的数字是属于哪个子网格的
首先我们假设子网格的序号如下编排:

由于1<=i、j<=9,我们有: (其中“/”是C++中对整数的除法)

令a= i/3 , b= j/3 ,根据九宫格的 行列 与 子网格 的 关系,我们有:

不难发现 3a+b=k
即 3*(i/3)+j/3=k
又我在程序中使用的数组下标为 1~9,grid编号也为1~9
因此上面的关系式可变形为 3*((i-1)/3)+(j-1)/3+1=k
有了这个推导的关系式,问题的处理就变得非常简单了,直接DFS即可
#include<iostream>
#include<cstdio>
#include<cstring> using namespace std; int map[][]; bool row[][]; //row[i][x] 标记在第i行中数字x是否出现了
bool col[][]; //col[j][y] 标记在第j列中数字y是否出现了
bool grid[][]; //grid[k][z ] 标记在第k个3*3子格中数字z是否出现了 bool DFS(int x,int y){
if(x==)
return true;
bool flag=false;
if(map[x][y]!=){
if(y==)
flag=DFS(x+,);
else
flag=DFS(x,y+);
//return flag;
if(flag) //回溯
return true;
else
return false;
}else{
int k=*((x-)/)+(y-)/+;
for(int i=;i<=;i++) //枚举数字1~9填空
if(!row[x][i] && !col[y][i] && !grid[k][i]){
map[x][y]=i;
row[x][i]=true;
col[y][i]=true;
grid[k][i]=true;
if(y==)
flag=DFS(x+,);
else
flag=DFS(x,y+);
if(flag) //回溯,继续枚举
return true;
else{
map[x][y]=;
row[x][i]=false;
col[y][i]=false;
grid[k][i]=false;
}
}
}
return false;
} int main(){ //freopen("input.txt","r",stdin); int t;
scanf("%d",&t); while(t--){
memset(row,false,sizeof(row));
memset(col,false,sizeof(col));
memset(grid,false,sizeof(grid));
char str[][];
for(int i=;i<=;i++){
//scanf("%s",str[i]+1); //为啥这样输入就不行了呢??纳闷ing,明天再弄吧
for(int j=;j<=;j++){
cin>>str[i][j];
map[i][j]=str[i][j]-'';
if(map[i][j]){
int k=*((i-)/)+(j-)/+;
row[i][map[i][j]]=true;
col[j][map[i][j]]=true;
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 ;
}
下面这个很快:
#include <iostream>
#include<cstdio>
#include<cstring> using namespace std; int num,v[][],map[][];
//bool pd[10][10]; //判断输入的时候是否为零 bool judge(int x,int y,int k){
int i,j,it,jt;
for(i=;i<;i++){
if(map[i][y]==k) return false;
if(map[x][i]==k) return false;
}
it=(x/)*;
jt=(y/)*;
for(i=;i<;i++)
for(j=;j<;j++)
if(map[i+it][j+jt]==k)
return false;
return true;
} int dfs(int cap){
int i,x,y;
if(cap<) return ; for(i=;i<=;i++){
x=v[cap][];
y=v[cap][];
if(judge(x,y,i)){
map[x][y]=i;
if(dfs(cap-)) return ;
map[x][y]=;
}
}
return ;
} int main(){
int t,i,j;
char c;
scanf("%d\n",&t);
while(t--){
num=;
for(i=;i<;i++,getchar())
for(j=;j<;j++){
scanf("%c",&c);
map[i][j]=c-'';
if(map[i][j]==){ //将为空的点的坐标全部记录下来,等下需要用暴力解决
v[num][]=i;
v[num++][]=j;
}
}
dfs(num-);
for(i=;i<;i++){
for(j=;j<;j++)
printf("%d",map[i][j]);
printf("\n");
}
}
return ;
}
POJ 2676 Sudoku (DFS)的更多相关文章
- POJ 2676 Sudoku(深搜)
Sudoku Time Limit : 4000/2000ms (Java/Other) Memory Limit : 131072/65536K (Java/Other) Total Submi ...
- POJ 2676 Sudoku (数独 DFS)
Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 14368 Accepted: 7102 Special Judg ...
- POJ 1190 生日蛋糕(DFS)
生日蛋糕 Time Limit: 1000MSMemory Limit: 10000KB64bit IO Format: %I64d & %I64u Submit Status Descrip ...
- poj2676 Sudoku(DFS)
做了很久还是参考了别人的答案orz,其实也不难啊.我要开始学一下怎么写搜索了... 题目链接:poj2676 Sudoku 题解:暴力搜索,DFS每个空白格子所放数字. #include<cst ...
- POJ - 3074 Sudoku (搜索)剪枝+位运算优化
In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For exa ...
- POJ 2531-Network Saboteur(DFS)
Network Saboteur Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9435 Accepted: 4458 ...
- 深搜+回溯 POJ 2676 Sudoku
POJ 2676 Sudoku Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 17627 Accepted: 8538 ...
- POJ 3414 Pots(罐子)
POJ 3414 Pots(罐子) Time Limit: 1000MS Memory Limit: 65536K Description - 题目描述 You are given two po ...
- POJ 2431 Expedition(探险)
POJ 2431 Expedition(探险) Time Limit: 1000MS Memory Limit: 65536K [Description] [题目描述] A group of co ...
随机推荐
- [Git] Squash all of my commits into a single one and merge into master
Often you have your feature branch you’ve been working on and once it’s ready, you just want it to m ...
- ASP入门(十六)-ASP开发的规范
毋容置疑,在开发中遵守一套规范,将会有利于提高代码的可读性,较低后期维护成本. 文件存放目录规范 js 目录下存放着页面所使用的 JavaScript 脚本文件,因为我们可能用到第三方提供的免费的 J ...
- Mac 隐私与安全没有允许任何来源选项
mac 允许任何来源的 app 在 macOS Sierra 10.12 及之后的版本,都没有 打开任何来源 的选项,解决方法: 终端执行命令: sudo spctl --master-disable
- 使用FractionSlider生成的视差幻灯效果原型
在线演示 本地下载 非常棒的jQuery插件,帮助你创建超酷的视差效果幻灯!
- Mybatis源码分析之Mapper执行SQL过程(三)
上两篇已经讲解了SqlSessionFactory的创建和SqlSession创建过程.今天我们来分析myabtis的sql是如何一步一步走到Excutor. 还是之前的demo public ...
- 论asp.net out、ref、return
论asp.net out.ref.return ref(引用类型) ref引用类型进出都必须赋值,赋值后会改变类型原来的指针. out(值类型) out值类型进可以不赋值,出必须赋值. return( ...
- VMware用于Site Recovery Manager 5的vSphere Replication功能一览
http://www.searchstorage.com.cn/showcontent_54838.htm 参考:深度解析SRM 5.0和vSphere Replication http://wenk ...
- Shell 字符串分割
入门级别 入门级别:类似1,2,3,4,5这样的字符串 #!/bin/bash var="1,2,3,4,5" var=${var//,/ } for i in $var; do ...
- 来自Unix/Linux的编程启发录
本篇文章已授权微信公众号 guolin_blog (郭霖)独家公布重点内容 2017年第一篇文章,祝各位好友新年快乐. 年前因为不小心坐到了自己左手大拇指导致轻微的骨裂,没有按时更新,实在是羞愧.今年 ...
- HDU1211 RSA
RSA Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...