【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
完善填数解数独
#include<stdio.h>
#include<string.h>
struct Avaliable
{
short row;
short col;
};
int OnlyAvaliable(short n)
{
return n!= 0 && ( n & ( n - 1 ) ) == 0;
}
int PointAvaliable(short n)
{
return n?PointAvaliable(n & ( n - 1 ))+1:0;
}
int getHighBit(short n)
{
int i = 0;
while(n)
{
n/=2;
i++;
}
return i-1;
}
Avaliable g_avas[9][9];
int g_solved = 0;
unsigned short g_SudokuMap[9][9] = {
// {1,3,0,0,6,8,0,0,0},
// {6,0,0,0,0,0,0,8,1},
// {5,0,0,0,4,0,2,0,0},
// {3,0,0,7,0,2,0,0,0},
// {4,1,7,0,8,0,3,5,2},
// {0,0,0,1,0,4,0,0,9},
// {0,0,4,0,7,0,0,0,8},
// {2,8,0,0,0,0,0,0,6},
// {0,0,0,8,9,0,0,2,5},
// 需要填数
{0,0,0,0,0,0,0,0,0},
{0,0,2,3,0,5,9,0,0},
{0,1,0,0,4,0,0,7,0},
{0,7,0,0,0,9,0,6,0},
{0,0,8,0,0,0,3,0,0},
{0,4,0,5,0,0,0,2,0},
{0,2,0,0,7,0,0,4,0},
{0,0,9,8,0,3,2,0,0},
{0,0,0,0,0,0,0,0,0},
// 困难
// {0,0,0,0,4,0,2,0,0},
// {0,1,0,0,0,6,0,0,9},
// {0,0,5,0,0,0,0,0,7},
// {0,0,0,9,0,7,0,0,6},
// {0,0,0,0,5,0,0,0,0},
// {2,0,0,8,0,3,0,0,0},
// {3,0,0,0,0,0,6,0,0},
// {4,0,0,2,0,0,0,8,0},
// {0,0,9,0,1,0,0,0,0},
};
void SolveSudoku(unsigned short SudokuMap[9][9],Avaliable avas[9][9],int n)
{
int i,j,k,l,temp,minava[3],result,count;
unsigned short l_SudokuMap[9][9];
Avaliable l_avas[9][9];
while( n > 0 )
{
minava[0] = 10;
minava[1] = -1;
minava[2] = -1;
for ( i = 0 ; i < 9 ; i++ )
{
for ( j = 0 ; j < 9 ; j++ )
{
temp = SudokuMap[i][j];
if ( temp == 0 )
{
result = avas[i][j].row & avas[i][j].col;
if ( OnlyAvaliable( result ) )
{
temp = getHighBit(result);
for( k = 0 ; k < 9 ; k++ )
{
avas[i][k].col &= ~( 1 << temp );
avas[k][j].row &= ~( 1 << temp );
avas[i/3*3+k/3][j/3*3+k%3].col &= ~( 1 << temp );
avas[i/3*3+k/3][j/3*3+k%3].row &= ~( 1 << temp );
}
avas[i][j].row = avas[i][j].col = 0;
SudokuMap[i][j] = temp;
n --;
}
}
}
}
for ( i = 0 ; i < 9 ; i++ )
{
for ( j = 0 ; j < 9 ; j++ )
{
temp = SudokuMap[i][j];
if ( temp == 0 )
{
result = avas[i][j].row & avas[i][j].col;
temp = PointAvaliable(result);
if( 0 < temp && temp < minava[0] )
{
minava[0] = temp;
minava[1] = i;
minava[2] = j;
}
}
}
}
if( 1 < minava[0] && minava[0] < 10 )
{
i = minava[1];
j = minava[2];
l = avas[i][j].row & avas[i][j].col;
temp = 1;
count = 0;
memcpy(l_SudokuMap,SudokuMap,sizeof(l_SudokuMap));
memcpy(l_avas,avas,sizeof(l_avas));
while( l > temp )
{
count++;
temp <<= 1;
if( l & temp )
{
l_SudokuMap[i][j] = count;
for( k = 0 ; k < 9 ; k++ )
{
l_avas[i][k].col &= ~temp;
l_avas[k][j].row &= ~temp;
l_avas[i/3*3+k/3][j/3*3+k%3].col &= ~temp;
l_avas[i/3*3+k/3][j/3*3+k%3].row &= ~temp;
}
l_avas[i][j].row = l_avas[i][j].col = 0;
SolveSudoku( l_SudokuMap,l_avas,n - 1 );
if(g_solved)
{
return;
}
else
{
l_SudokuMap[i][j] = 0;
for( k = 0 ; k < 9 ; k++ )
{
l_avas[i][k].col |= temp;
l_avas[k][j].row |= temp;
l_avas[i/3*3+k/3][j/3*3+k%3].col |= temp;
l_avas[i/3*3+k/3][j/3*3+k%3].row |= temp;
}
l_avas[i][j].row = avas[i][j].row;
l_avas[i][j].col = avas[i][j].col;
}
}
}
//既然到了填数的阶段了,说明前面填数除了冲突,可以回溯。
return ;
}
else if( minava[0] == 10 && n != 0)
{
return;
}
//因为n--在内部,所以可能出现了填好的状态。
}
memcpy(g_SudokuMap,SudokuMap,sizeof(g_SudokuMap));
g_solved = 1;
}
int main()
{
Avaliable (*avas)[9]=g_avas;
unsigned short (*SudokuMap)[9]=g_SudokuMap;
int i,j,k,temp,unsolved = 81;
for ( k = ( 1 << 10 ) - 2, i = 0 ; i < 9 ; i++ )
{
for ( j = 0 ; j < 9 ; j++ )
{
avas[i][j].row = avas[i][j].col = k;
}
}
for ( i = 0 ; i < 9 ; i++ )
{
for ( j = 0 ; j < 9 ; j++ )
{
temp = SudokuMap[i][j];
if( temp != 0 )
{
for( k = 0 ; k < 9 ; k++ )
{
avas[i][k].col &= ~( 1 << temp );
avas[k][j].row &= ~( 1 << temp );
avas[i/3*3+k/3][j/3*3+k%3].col &= ~( 1 << temp );
avas[i/3*3+k/3][j/3*3+k%3].row &= ~( 1 << temp );
}
avas[i][j].row = avas[i][j].col = 0;
unsolved --;
}
}
}
SolveSudoku(SudokuMap,avas,unsolved);
for ( i = 0 ; i < 9 ; i++ )
{
for ( j = 0 ; j < 9 ; j++ )
{
printf("%-3d",SudokuMap[i][j]);
}
printf("\n");
}
}
来源:oschina
链接:https://my.oschina.net/u/3695598/blog/3141406