Sudoku Killer
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 10645 Accepted Submission(s): 3152
Problem Description
自从2006年3月10日至11日的首届数独世界锦标赛以后,数独这项游戏越来越受到人们的喜爱和重视。
据说,在2008北京奥运会上,会将数独列为一个单独的项目进行比赛,冠军将有可能获得的一份巨大的奖品———HDU免费七日游外加lcy亲笔签名以及同hdu acm team合影留念的机会。
所以全球人民前仆后继,为了奖品日夜训练茶饭不思。当然也包括初学者linle,不过他太笨了又没有多少耐性,只能做做最最基本的数独题,不过他还是想得到那些奖品,你能帮帮他吗?你只要把答案告诉他就可以,不用教他是怎么做的。
数独游戏的规则是这样的:在一个9x9的方格中,你需要把数字1-9填写到空格当中,并且使方格的每一行和每一列中都包含1-9这九个数字。同时还要保证,空格中用粗线划分成9个3x3的方格也同时包含1-9这九个数字。比如有这样一个题,大家可以仔细观察一下,在这里面每行、每列,以及每个3x3的方格都包含1-9这九个数字。
例题:
答案:
Input
本题包含多组测试,每组之间由一个空行隔开。每组测试会给你一个 9*9 的矩阵,同一行相邻的两个元素用一个空格分开。其中1-9代表该位置的已经填好的数,问号(?)表示需要你填的数。
Output
对于每组测试,请输出它的解,同一行相邻的两个数用一个空格分开。两组解之间要一个空行。
对于每组测试数据保证它有且只有一个解。
这题很考验编码能力,两组数据空行,输入最好要用字符串来处理输入的空格换行,搜索时还要注意位置搜索不到后的回溯,单个点确定的九宫格判断 & 行列重复判断,搜索从0开始到所有的'?'均确定
练习时这个题目标签是基础搜索题...其实还是很有难度的
AC Code:
#include <cstdio>
#include <cmath>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<map>
#include<queue>
#include<climits>
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
using namespace std;
typedef long long ll;
static const int MAX_N = 1e6 + 5;
typedef pair<int, int> P; //记录坐标
P vv[80];
int maps[10][10];
int len;
bool flag;
bool is_rigth(int x, int y, int z) {
for(int i = 0; i < 9; i++){
if(maps[i][y] == z) return false;
if(maps[x][i] == z) return false; //判断行列
}
int fx = x / 3 * 3, fy = y / 3 * 3; //确定所在九宫格
for(int i = fx; i < fx + 3; i++){
for(int j = fy; j < fy + 3; j++){
if(maps[i][j] == z) return false; //九宫格判断
}
}
return true;
}
void dfs(int s) {
if(flag) return; //剪枝
if(s == len){
for(int i = 0; i < 9; i++){
for(int j = 0; j < 8; j++){
printf("%d ", maps[i][j]);
}
printf("%d\n", maps[i][8]);
}
flag = true;
return ;
}
for(int i = 1; i <= 9; i++){
if(flag) return ; //剪枝
if(is_rigth(vv[s].first, vv[s].second, i)) {
maps[vv[s].first][vv[s].second] = i;
dfs(s + 1);
if(flag) return; //剪枝
}
}
maps[vv[s].first][vv[s].second] = 0; //回溯(该点选择不合适,重新置0)
}
int main(){
char s[2];
while(scanf("%s", s) != EOF) {
maps[0][0] = (s[0] == '?' ? 0 : s[0] - '0'); //第1行第1个
for(int j = 1; j < 9; j++){
scanf("%s", s);
maps[0][j] = (s[0] == '?' ? 0 : s[0] - '0'); //第1行后8个
}
for(int i = 1; i < 9; i++){
for(int j = 0; j < 9; j++) {
scanf("%s", s);
maps[i][j] = (s[0] == '?' ? 0 : s[0] - '0'); //2 - 9行
}
}
len = 0;
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
if(maps[i][j] == 0) {
vv[len].first = i, vv[len++].second = j;
}
}
}
if(flag) printf("\n"); //之前有过输入
flag = false;
dfs(0);
}
return 0;
}