HDU 1426 Sudoku Killer

此题输入格式十分奇怪,用scanf("%s",s );来收下每个字符就能忽略空格的影响了。

思路是简单DFS,把每个为问号的点存下来进行DFS枚举,枚举时判断下能否放入该数字然后回溯结果即可。

附渣代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <memory.h>
#include <queue>
#define MAX 82
using namespace std;

struct node{
    int i,j;
}ans[MAX],sudu[3][3];

int cs,flag;
char map[10][10];

void printmap()
{
    int i,j;
    for(i=0;i<9;i++){
            for(j=0;j<9;j++){
                printf(j==8?"%c\n":"%c ",map[i][j]);
            }
        }
}

bool judge(int p,int x)//判断改点为x是否可行
{
    int row=ans[p].i,cl=ans[p].j;
    int i,j;
    for(i=0;i<9;i++){
        if((map[row][i]!='?')&&(map[row][i]-'0'==x))//行
        return 0;
        if((map[i][cl]!='?')&&(map[i][cl]-'0'==x))//列
        return 0;
    }
    i=ans[p].i/3;      //计算改点所在小方块的位置
    j=ans[p].j/3;
    row=sudu[i][j].i;
    cl=sudu[i][j].j;
    for(i=row;i<row+3;i++){
        for(j=cl;j<cl+3;j++){
            if((map[i][j]!='?')&&(map[i][j]-'0'==x))
            return 0;
        }
    }
    return 1;
}

void dfs(int nodei)
{
    if(flag)return;
    if(nodei==cs){
        flag=1;
        printmap();
    }
    int i;
    for(i=1;i<=9;i++){
        if(!judge(nodei,i))
            continue;
        char c;
        c=map[ans[nodei].i][ans[nodei].j];
        map[ans[nodei].i][ans[nodei].j]=i+'0';//设置回溯
        dfs(nodei+1);
        if(flag)
        return ;
        map[ans[nodei].i][ans[nodei].j]=c;//回溯
    }
}

int main()
{
    sudu[0][0].i=0;sudu[0][0].j=0;
    sudu[0][1].i=0;sudu[0][1].j=3;
    sudu[0][2].i=0;sudu[0][2].j=6;
    sudu[1][0].i=3;sudu[1][0].j=0;
    sudu[1][1].i=3;sudu[1][1].j=3;
    sudu[1][2].i=3;sudu[1][2].j=6;
    sudu[2][0].i=6;sudu[2][0].j=0;
    sudu[2][1].i=6;sudu[2][1].j=3;
    sudu[2][2].i=6;sudu[2][2].j=6;//存放数独9个小方块的左上角坐标
    int i,j;
    char s[10];
    int casi=0;
    while(scanf("%s",s)!=EOF){
        if(casi!=0)
        printf("\n");//输出格式:每个CASE间有空行,结尾没有空行。
        casi++;
        cs=0;
        map[0][0]=s[0];
        if(map[0][0]=='?'){
            ans[cs].i=0;
            ans[cs].j=0;
            cs++;
        }
        for(i=0;i<9;i++){
            if(i==0)j=1;
            else j=0;
            for(;j<9;j++){
                scanf("%s",s);      //用字符串输入,每次取s[0]
                map[i][j]=s[0];
                if(map[i][j]=='?'){
                    ans[cs].i=i;
                    ans[cs++].j=j;
                }
            }
        }
        flag=0;
        dfs(0);
    }
    return 0;
}
其实可以用来解所有数独。。。只是因为是根据问号数目进行递归,要是问号过多或者DFS树需要的节点很多就可能很慢甚至超栈。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值