zoukankan      html  css  js  c++  java
  • Sudoku Solver

    Write a program to solve a Sudoku puzzle by filling the empty cells.

    Empty cells are indicated by thecharacter '.'.

    You may assume that there will be only one unique solution.

     

                    


    思路:本题是典型的回溯法题型,类似的题目还有迷宫求解,8皇后问题。回溯法解题的一般思路是深度优先算法


    若采用递归求解,轮训所有状态(分支),找到一个合法状态,就继续递归深入,如果不合法,则轮训下一个状态(下一个分支)。如果所有状态都轮训完还没有找到合法状态,则恢复为原始状态后,直接返回(剪枝),回溯到上一个状态。如不采用递归,则使用栈,模拟递归。


    本题在解决数独问题时,首先在第一个”.”处,从1到9,分别判断那个值是合法的,找到一个合法值,则寻找第二个”.”,依次深入。如果某个节点,从1到9都不合法,则恢复该节点的状态(”.”),然后回溯到上一个”.”处,继续轮训下一个状态。


    剩下的问题就是,如何判断某个值是否合法,很简单,从该值所处的行、列和区域内,查看是否有重复的值即可。代码如下,包含了递归和非递归的算法:

    <pre name="code" class="cpp">typedef struct
    {
    	int i, j;
    	int value;
    }node;
    
    typedef struct
    {
    	node **sets;
    	int len;
    	int top;
    }Stack;
    
    int push(Stack *s, node *key)
    {
    	if(s->top >= s->len)  return -1;
    
    	s->sets[s->top ++] = key;
    
    	return 0;
    }
    
    node *pop(Stack *s)
    {
    	if(s->top == 0)   return NULL;
    	return s->sets[-- s->top];
    }
    
    Stack *initstack(int stlen)
    {
    	Stack *st = calloc(1, sizeof(Stack));
    	st->sets = calloc(stlen, sizeof(node *));
    	st->len = stlen;
    	st->top = 0;
    
    	return st;
    }
    
    void freestack(Stack *s)
    {
    	node *top = NULL;
    	while((top = pop(s)) != NULL)
    	{
    		free(top);
    	}
    	free(s);
    }
    
    int isSafe(char** board, int boardRowSize, int boardColSize, node *top) 
    {
    	int i, j, value;
    	int tmp = -1;
    	i = top->i;
    	j = top->j;
    	value = top->value;
    
    	int m, n;
    	for(m = 0; m < boardColSize; m++)
    	{
    		if(m == j)	continue;
    		tmp = board[i][m] - '0';
    		if(tmp == value)	return 0;
    	}
    
    	for(m = 0; m < boardRowSize; m++)
    	{
    		if(m == i)	continue;
    		tmp = board[m][j] - '0';
    		if(tmp == value)	return 0;
    	}
    
    	int lineend = i/3 * 3 + 3;
    	int colend = j/3 * 3 + 3;
    	for(m = i/3 * 3; m < lineend; m++)
    	{
    		for(n = j/3 * 3; n < colend; n++)
    		{
    			if(m == i && n == j)	continue;
    			tmp = board[m][n] - '0';
    			if(tmp == value)	return 0;
    		}
    	}
    
    	return 1;
    }
    
    void solveSudoku_loop(char **board, int boardRowSize, int boardColSize)
    {
    	int i, j, tmp;
    	Stack *s = initstack(81);
    	node *top = NULL;
    
    	for(i = 0; i < boardRowSize; i++)
    	{
    		for(j = 0; j < boardColSize; j++)
    		{
    			if(board[i][j] == '.')
    			{
    				node *newnode = calloc(1, sizeof(node));
    				newnode->i = i;
    				newnode->j = j;
    				newnode->value = 1;
    				board[i][j] = newnode->value + '0';
    				push(s, newnode);
    				top = newnode;
    				while(isSafe(board, boardRowSize, boardColSize, top) == 0)
    				{
    					top = pop(s);
    					while(top != NULL && top->value == 9)	
    					{
    						board[top->i][top->j] = '.';
    						top = pop(s);
    					}
    					if(top == NULL)	
    					{
    						printf("no solution
    ");
    						freestack(s);
    						return;
    					}
    
    					top->value += 1;
    					board[top->i][top->j] = top->value + '0';
    					push(s, top);
    				}
    				i = top->i;
    				j = top->j;
    			}
    		}
    	}
    	freestack(s);
    }
    
    
    int findemptyblank(char **board, int boardRowSize, int boardColSize, int *i, int *j)
    {
    	int m, n;
    	for(m = 0; m < boardRowSize; m++)
    	{
    		for(n = 0; n < boardColSize; n++)
    		{
    			if(board[m][n] == '.')
    			{
    				*i = m;
    				*j = n;
    				return 1;
    			}
    		}
    	}
    	return 0;
    }
    
    int solveSudoku_recurse(char **board, int boardRowSize, int boardColSize)
    {
    	int i, j, k;
    
    	if(findemptyblank(board, boardRowSize, boardColSize, &i, &j) == 0)
    	{
    		return 1;
    	}
    
    	node newnode;
    	newnode.i = i;
    	newnode.j = j;
    	
    	for(k = 1; k <= 9; k++)
    	{
    		newnode.value = k;
    		if(isSafe(board, boardRowSize, boardColSize, &newnode))
    		{
    			board[i][j] = k + '0';
    			if(solveSudoku_recurse(board, boardRowSize, boardColSize))
    			{
    				return 1;
    			}
    		}
    	}
    	board[i][j] = '.';
    	return 0;
    }
    
    
    int isValidSudoku(char** board, int boardRowSize, int boardColSize) 
    {
    	int hashline[10][10];
    	int hashcol[10][10];
    	int hashzone[10][10];
    	int i, j;
    	int tmp = -1;
    	int zone = -1;
    	for(i = 0; i < 10; i++)
    	{
    		for(j = 0; j < 10; j++)
    		{
    			hashline[i][j] = hashcol[i][j] = hashzone[i][j] = 0;
    		}
    	}
        
    	for(i = 0; i < boardRowSize; i++)
    	{
    		for(j = 0; j < boardColSize; j++)
    		{
    			tmp = board[i][j];
    			if(tmp == '.')  continue;
    			else    tmp = tmp - '0';
    
    			zone = (i / 3) * 3 + j / 3;
    			if(hashline[tmp][i]) return 0;
    			if(hashcol[tmp][j]) return 0;
    			if(hashzone[tmp][zone]) return 0;
    
    			hashline[tmp][i] = hashcol[tmp][j] = hashzone[tmp][zone] = 1;
    		}
    	}
    	return 1;
    }
    
    void printsudoku(char** board, int boardRowSize, int boardColSize)
    {
    	int i, j;
    	printf("
    ");
    	for(i = 0; i < boardRowSize; i++)
    	{
    		if(i % 3 == 0)
    		{
    			printf("--------------------
    ");
    		}
    		for(j = 0; j < boardColSize; j++)
    		{
    			if(j % 3 == 0)
    			{
    				printf("|");
    			}
    			printf("%c ", board[i][j]);
    		}
    		
    		printf("
    ");
    	}
    }
    
    void solveSudoku(char **board, int boardRowSize, int boardColSize)
    {
    	solveSudoku_loop(board, boardRowSize, boardColSize);	
    	//solveSudoku_recurse(board, boardRowSize, boardColSize);
    }


    
       
    
    
  • 相关阅读:
    PetaPoco 基础操作
    Sql Server实现自动增长
    冒泡排序算法[C++]
    PHP 使用非对称加密算法(RSA)
    Linux的PHP开发环境快速搭建
    PHP常见漏洞攻击简述
    关于计算机编码的笔记
    简述面向对象编程原则和设计模式
    PHP错误处理注册机制
    规范数据库设计
  • 原文地址:https://www.cnblogs.com/gqtcgq/p/7247142.html
Copyright © 2011-2022 走看看