您的位置:首页 > 其它

HDU 1426 Sudoku Killer

2011-07-09 00:41 405 查看
此题输入格式十分奇怪,用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树需要的节点很多就可能很慢甚至超栈。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c