hdu1426Sudoku Killer解题报告---数独(深搜 & 回溯 & 输入格式控制)

版权声明:转载请注明出处:https://blog.csdn.net/qq1013459920 https://blog.csdn.net/qq1013459920/article/details/84729773

                                            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;
}

猜你喜欢

转载自blog.csdn.net/qq1013459920/article/details/84729773