您的位置:首页 > 其它

数独算法求解

2009-08-13 12:05 543 查看
//===============================================
//filename:shudu.cpp
//author:andy
//date:2009/08/13
//================================================

#include "stdio.h"
#include "malloc.h"
#include "memory.h"

//#define __LINUX__
//#define __DEBUG__

#ifdef __LINUX__
#include "stdbool.h"
#endif

#ifdef __DEBUG__
#define DEBUG_TRACE printf
#else
#ifdef __LINUX__
#define DEBUG_TRACE(...)
#else
void my_printf(...)
{
}
#define DEBUG_TRACE my_printf
#endif
#endif

typedef enum
{
CALC_FINISH,
CALC_UNFINISH,
CALC_ERROR
}CALC_STATE;

typedef struct _TRACE_VALUE
{
int row;
int column;
int value;
struct _TRACE_VALUE *next;
}trace_value,*trace_value_p;

typedef struct _TRACE_NODE
{
int row;
int column;
int value_index;
int *values;
trace_value_p gen_value;
struct _TRACE_NODE *next;
}trace_node;

void print_shudu(int shudu[][9])
{
int i,j;

for (i=0;i<9;i++)
{
for (j=0;j<9;j++)
{
printf("%4d",shudu[i][j]);
}
printf("/n");
}
}

bool match_row_number(int shudu[][9],int row, int number)
{
bool match = false;
int i;

for (i=0;i<9;i++)
{
if (number == shudu[row][i])
{
match = true;
break;
}
}

return match;
}

bool match_column_number(int shudu[][9],int column, int number)
{
bool match = false;
int i;

for (i=0;i<9;i++)
{
if (number == shudu[i][column])
{
match = true;
break;
}
}

return match;
}

void calc_candidate(int shudu[][9], int row, int column, int candidate[10])
{
int i=0,j=0;

for (i=0;i<=9;i++)
{
candidate[i] = (i+1)%10;
}

for (i=0;i<9;i++)
{
if (0 != shudu[row][i])
{
candidate[shudu[row][i]-1] = 0;
}

if (0 != shudu[i][column])
{
candidate[shudu[i][column]-1] = 0;
}

if (0 != shudu[row-row%3+i/3][column-column%3+i%3])
{
candidate[shudu[row-row%3+i/3][column-column%3+i%3]-1] = 0;
}
}

for (i=0,j=0;i<9;i++)
{
if (0 != candidate[i])
{
candidate[j++] = candidate[i];
if (i+1 != j)
candidate[i] = 0;
}
}
}

CALC_STATE calc_shudu(int shudu[][9],int row, int column, int *possible_num_cnt)
{
int i,j;
int value[10]={1,2,3,4,5,6,7,8,9};
int final_value = 0;

calc_candidate(shudu, row, column, value);

if (0 == value[0])
{
return CALC_ERROR;
}

for (i=0;i<9 && 0!= value[i];i++);

*possible_num_cnt = i;

if (1 == i)
{
shudu[row][column] = final_value;
DEBUG_TRACE("calc row=%d,column=%d,value=%d/n",row,column,final_value);
}
else
{
for (i=0;i<9;i++)
{
if (0 != value[i])
{
int row_1 = (2==row%3 ? row-2:row+1);
int row_2 = (0==row%3 ? row+2:row-1);
int column_1 = (2==column%3 ? column-2:column+1);
int column_2 = (0==column%3 ? column+2:column-1);

if (match_row_number(shudu,row_1,value[i])
&& match_row_number(shudu,row_2,value[i]))
{
if ((0!= shudu[row][column_1] || match_column_number(shudu,column_1,value[i]))
&& (0!= shudu[row][column_2] || match_column_number(shudu,column_2,value[i])))
{
shudu[row][column] = value[i];
DEBUG_TRACE("row match row=%d,column=%d,value=%d/n",row,column,value[i]);
break;
}
}

if (match_column_number(shudu,column_1,value[i])
&& match_column_number(shudu,column_2,value[i]) )
{
if ((0!= shudu[row_1][column] || match_row_number(shudu,row_1,value[i]) )
&& (0!= shudu[row_2][column] || match_row_number(shudu,row_2,value[i])))
{
shudu[row][column] = value[i];
DEBUG_TRACE("column match row=%d,column=%d,value=%d/n",row,column,value[i]);
break;
}
}
}
}
}

return 0!= shudu[row][column] ? CALC_FINISH : CALC_UNFINISH;
}

void add_trace(trace_node **shudu_trace, int row,int column,int candidate[10])
{
int i=0;
trace_node * node = (trace_node *)malloc(sizeof(trace_node));

while (i<9)
{
if (0 == candidate[i])
break;
i++;
}

node->row = row;
node->column = column;
node->value_index = 0;
node->values = (int *)malloc(sizeof(int)*(i+1));
memcpy(node->values, candidate, sizeof(int)*(i+1));
node->gen_value = NULL;

node->next = *shudu_trace;
*shudu_trace = node;

DEBUG_TRACE("==============add trace row=%d,column=%d,value=%d/n",row,column,candidate[0]);
}

bool rollback(int shudu[][9], trace_node ** shudu_trace)
{
trace_node *node = NULL;
trace_value *value_node,*value_node_pre;

if (NULL == shudu_trace || NULL == *shudu_trace)
{
return false;
}

value_node = (*shudu_trace)->gen_value;

while (NULL != value_node)
{
shudu[value_node->row][value_node->column] = 0;
value_node_pre = value_node;
value_node = value_node->next;
free(value_node_pre);
}

DEBUG_TRACE("/n rollback shudu gen value/n");
#ifdef __DEBUG__
print_shudu(shudu);
#endif

(*shudu_trace)->gen_value = NULL;

if (0 == (*shudu_trace)->values[(*shudu_trace)->value_index+1])
{
node = *shudu_trace;
*shudu_trace = (*shudu_trace)->next;

shudu[node->row][node->column]  = 0;

free(node->values);
free(node);
return rollback(shudu, shudu_trace);
}
else
{
(*shudu_trace)->value_index++;
shudu[(*shudu_trace)->row][(*shudu_trace)->column] = (*shudu_trace)->values[(*shudu_trace)->value_index];
//*trace_index = (*shudu_trace)->row * 9 + (*shudu_trace)->column;
DEBUG_TRACE("rollback add trace row=%d,column=%d,value=%d/n",
(*shudu_trace)->row,(*shudu_trace)->column,shudu[(*shudu_trace)->row][(*shudu_trace)->column]);
}

return true;
}

CALC_STATE generate_new_number(int shudu[][9], trace_node **shudu_trace, int *next_trace_index)
{
int i=0,j=0;
bool generate_new = false;
bool finish = true;
bool generate_state = true;
CALC_STATE calc_single_state;
int possible_num_cnt;
int min_possible_cnt = 10;
//return CALC_UNFINISH;

do
{
finish = true;
generate_new = false;
min_possible_cnt = 10;

for (i=0;i<9;i++)
for (j=0;j<9;j++)
{
if (0 == shudu[i][j])
{
calc_single_state = calc_shudu(shudu,i,j,&possible_num_cnt);

if (CALC_FINISH == calc_single_state)
{
generate_new = true;

if (NULL != shudu_trace && NULL != *shudu_trace)
{
trace_value *value_node = (trace_value *)malloc(sizeof(trace_value));

value_node->row = i;
value_node->column = j;
value_node->value = shudu[i][j];
value_node->next = (*shudu_trace)->gen_value;
(*shudu_trace)->gen_value = value_node;
//DEBUG_TRACE("generate new row=%d,column=%d,value=%d/n",i,j,shudu[i][j]);
}
}
else if (CALC_UNFINISH == calc_single_state)
{
if (min_possible_cnt > possible_num_cnt)
{
*next_trace_index = i*9+j;
min_possible_cnt = possible_num_cnt;
}
}
else if (CALC_ERROR == calc_single_state)
{
DEBUG_TRACE("/n error shudu in row=%d,column=%d/n",i,j);
#ifdef __DEBUG__
print_shudu(shudu);
#endif
return CALC_ERROR;
}
}

if (0 == shudu[i][j])
{
finish = false;
}
}

}while (generate_new && !finish);

return finish ? CALC_FINISH : CALC_UNFINISH;
}

void shudu_solution(int shudu[][9])
{
int i,j;
int next_trace_index=0;
trace_node *shudu_trace=NULL;
bool  finish = false;
int   candidate[10];
CALC_STATE gen_state;

while (!finish)
{
gen_state = generate_new_number(shudu, &shudu_trace, &next_trace_index);

if (CALC_FINISH == gen_state)
{
finish = true;
}
else if (CALC_UNFINISH == gen_state)
{
calc_candidate(shudu, next_trace_index/9, next_trace_index%9,candidate);
shudu[next_trace_index/9][next_trace_index%9] = candidate[0];
add_trace(&shudu_trace,next_trace_index/9, next_trace_index%9,candidate);
}
else if (CALC_ERROR == gen_state)
{
if (!rollback(shudu,&shudu_trace))
{
finish = true;
DEBUG_TRACE("/noh my god,it is so hard,i can not fix it,wuwu,or maybe you cheat me/n");
}
}
}

printf("/nhaha,the result is:/n");
print_shudu(shudu);

return;
}

int main(void)
{
int shudu[9][9]={0};
int blank_count=0;
int i=0,j=0;
CALC_STATE gen_state;

printf("please input the shudu number :");

for (i=0;i<9;i++)
for (j=0;j<9;j++)
{
scanf("%1d", &shudu[i][j]);
if (0 == shudu[i][j])
{
blank_count++;
}
}

DEBUG_TRACE("/nthe number you input is:/n");
#ifdef __DEBUG__
print_shudu(shudu);
#endif

shudu_solution(shudu);

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: