Sudoku Killer
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3723 Accepted Submission(s): 1170
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这九个数字。
例题:
答案:
据说,在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
对于每组测试,请输出它的解,同一行相邻的两个数用一个空格分开。两组解之间要一个空行。
对于每组测试数据保证它有且只有一个解。
对于每组测试数据保证它有且只有一个解。
Sample Input
7 1 2 ? 6 ? 3 5 8
? 6 5 2 ? 7 1 ? 4
? ? 8 5 1 3 6 7 2
9 2 4 ? 5 6 ? 3 7
5 ? 6 ? ? ? 2 4 1
1 ? 3 7 2 ? 9 ? 5
? ? 1 9 7 5 4 8 6
6 ? 7 8 3 ? 5 1 9
8 5 9 ? 4 ? ? 2 3
Sample Output
7 1 2 4 6 9 3 5 8
3 6 5 2 8 7 1 9 4
4 9 8 5 1 3 6 7 2
9 2 4 1 5 6 8 3 7
5 7 6 3 9 8 2 4 1
1 8 3 7 2 4 9 6 5
2 3 1 9 7 5 4 8 6
6 4 7 8 3 2 5 1 9
8 5 9 6 4 1 7 2 3
Author
linle
Source
ACM暑期集训队练习赛(三)
Recommend
LL | We have carefully selected several similar problems for you: 1258 1045 2614 1067 1312
DFS搜索,进阶题目。
题意是给你多个数独题目,让你输出它们的答案。
思路是递归确定每一个‘?’的位置的值,直到所有‘?’都被确定。先将原字符数组转换为整型数组,‘?’由数字0代替,然后每一次层递归找到第一个0的位置,如果找到了,找出当前位置所有可以放置的数字,依次尝试,每次假设把这个数放在当前位置,然后再确认下一个0位置的数字,直到数组中找不到0,即是正确结果(递归出口)。
注意输入格式,要求输入的每组数据之间有一个空行,可以先单独输入第一组数据,后面的数据都是先读取空行,再读取数据。
题目给的测试数据很弱,献上一组我的测试数据,如果你总是WA可以试试:
? 5 ? 4 ? 8 ? ? 2
? ? 1 ? ? 5 7 3 ?
? 6 2 ? ? 7 ? ? 9
? ? 8 ? 6 3 2 ? 7
3 ? ? 1 ? ? ? ? 6
5 ? 6 2 ? ? 9 ? ?
4 ? ? 7 ? ? 8 2 ?
? 1 7 8 ? ? 3 ? ?
2 ? ? 9 ? 1 ? 7 ?
答案:
7 5 3 4 9 8 1 6 2
9 4 1 6 2 5 7 3 8
8 6 2 3 1 7 4 5 9
1 9 8 5 6 3 2 4 7
3 2 4 1 7 9 5 8 6
5 7 6 2 8 4 9 1 3
4 3 9 7 5 6 8 2 1
6 1 7 8 4 2 3 9 5
2 8 5 9 3 1 6 7 4
注意如果这一步的所有情况都判定失败,返回上一层递归的时候不要忘了将当前位置还原为“?”的状态,否则会影响以后的递归。
代码量比别人长了一些,速度也达到了400MS左右,但好在关键地方都做了注释,代码还算好懂,看官们有改进意见可以跟我提。
不费话了,上代码:
1 #include2 #include '; 11 else 12 cout<<b[i][j]; 13 cout<<endl; 14 } 15 } 16 void char2int(char a[9][20],int b[9][9]) //字符二维数组向整型二维数组转换 17 { 18 int i,j; 19 for(i=0;i<9;i++) 20 for(j=0;j<18;j++) 21 if(a[i][j]=='?') 22 b[i][j/2] = 0; 23 else if('1'<=a[i][j] && a[i][j]<='9') 24 b[i][j/2] = a[i][j]-'0'; 25 } 26 bool judge(int curx,int cury,int num,const int b[9][9]) 27 { 28 int i,j; 29 //查找一横行 30 for(i=0;i<9;i++) //将这一行出现的数字全部设为不可填 31 if(i!=cury && b[curx][i]==num) 32 return true; 33 //查找一竖列 34 for(i=0;i<9;i++) //将这一行出现的数字全部设为不可填 35 if(i!=curx && b[i][cury]==num) 36 return true; 37 //查找当前九宫格 38 int x,y; 39 x = curx/3*3; 40 y = cury/3*3; 41 for(i=0;i<3;i++) 42 for(j=0;j<3;j++) 43 if(x+i!=curx && y+j!=cury && b[x+i][y+j]==num) 44 return true; 45 return false; 46 } 47 bool dfs(int b[9][9]) 48 { 49 //找到当前第一个'?'位置。如果没有找到,表示所有位置都已填上,即为正确结果,递归结束 50 int i,j; 51 for(i=0;i<9;i++) 52 for(j=0;j<9;j++) 53 if(b[i][j]==0) //找'?'的位置 54 goto label; 55 label: 56 if(i>=9 && j>=9) //找到正确结果了,递归结束 57 return true; 58 //记录坐标 59 int curx = i,cury = j; 60 //确定该位置的可以填的数字 61 bool temp[10]; //记录哪些数字可以填 62 int num=0; //记录当前位置可以填的数字的个数 63 for(i=1;i<=9;i++) 64 if(judge(curx,cury,i,b)) //判断这个位置可不可以放这个数字 65 temp[i] = false; 66 else { 67 temp[i] = true; 68 num++; 69 } 70 if(num==0) 71 return false; 72 //确定下一个位置 73 for(i=1;i<=9;i++) 74 if(temp[i]){ 75 //这个数在这个位置可以填 76 if(judge(curx,cury,i,b)) 77 continue; 78 b[curx][cury] = i; 79 if(dfs(b)) 80 return true; 81 } 82 b[curx][cury] = 0; //这句千万别忘了写,就是这一步不能走的记得还原为0 83 return false; 84 } 85 int main() 86 { 87 char a[9][20]; 88 int b[9][9]; 89 int i; 90 for(i=0;i<9;i++) 91 cin.getline(a[i],20,'\n'); 92 char2int(a,b); //char数组转换为int数组 93 if(dfs(b)) //产生结果 94 putoutint(b); //输出数组内容 95 96 while(cin.getline(a[0],20,'\n')){ //读取空行,或者到文件尾 97 cout<<endl; 98 char a[9][20]; 99 int b[9][9]; 100 int i; 101 for(i=0;i<9;i++) 102 cin.getline(a[i],20,'\n'); 103 char2int(a,b); //char数组转换为int数组 104 if(dfs(b)) //产生结果 105 putoutint(b); //输出数组内容 106 } 107 return 0; 108 }3 using namespace std; 4 void putoutint(int b[9][9]) //输出整型二维数组 5 { 6 int i,j; 7 for(i=0;i<9;i++){ 8 for(j=0;j<9;j++) 9 if(j!=8) 10 cout<'
Freecode : www.cnblogs.com/yym2013