Poj 3074: Sudoku

Description

In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example,

. 2 7 3 8 . . 1 .
. 1 . . . 6 7 3 5
. . . . . . . 2 9
3 . 5 6 9 2 . 8 .
. . . . . . . . .
. 6 . 1 7 4 5 . 3
6 4 . . . . . . .
9 5 1 8 . . . 7 .
. 8 . . 6 5 3 4 .

Given some of the numbers in the grid, your goal is to determine the remaining numbers such that the numbers 1 through 9 appear exactly once in (1) each of nine 3 × 3 subgrids, (2) each of the nine rows, and (3) each of the nine columns.

Input

The input test file will contain multiple cases. Each test case consists of a single line containing 81 characters, which represent the 81 squares of the Sudoku grid, given one row at a time. Each character is either a digit (from 1 to 9) or a period (used to indicate an unfilled square). You may assume that each puzzle in the input will have exactly one solution. The end-of-file is denoted by a single line containing the word “end”.

Output

For each test case, print a line representing the completed Sudoku puzzle.

Sample Input

.2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.
......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.
end

Sample Output

527389416819426735436751829375692184194538267268174593643217958951843672782965341
416837529982465371735129468571298643293746185864351297647913852359682714128574936

Source

Stanford Local 2006

用Dancing-Links玩数独

324个限制

1-81列,每个格子是否填数

82-162列,每行1-9的填写情况

163-243列,每列1-9的填写情况

244-324列,每宫1-9的填写情况

然后暴力跑Dancing-Links就好了

为什么感觉爆搜题很码农啊

#include 
using namespace std;

const int MAXN = 6020;
const int MAXM = 350;
const int INF = 1e9 + 7;

int L[MAXN], R[MAXN], U[MAXN], D[MAXN], S[MAXM];
int pos[MAXN], Col[MAXN];
int mp[MAXN][MAXM];
int head[10][10][10], cnt;
char ch[100];

inline void init()
{
	for( int i = 0 ; i <= 324 ; i++ )
		S[ i ] = 0, L[ i ] = i - 1, R[ i ] = i + 1, U[ i ] = D[ i ] = i;
	L[ R[ 324 ] = 0 ] = cnt = 324;
}

inline int getpos(int x, int y) { return ( x - 1 ) / 3 * 3 + ( y - 1 ) / 3; } 

inline void insert(int c, int cnt)
{
	U[ D[ U[ c ] ] = cnt ] = U[ c ];
	D[ U[ c ] = cnt ] = c;
	S[ c ]++;
	Col[ cnt ] = c; 
}

inline void ins(int x, int y, int k)
{
	for( int i = cnt + 1 ; i <= cnt + 4 ; i++ )
		L[ i ] = i - 1, R[ i ] = i + 1, pos[ i ] = 100 * x + 10 * y + k;
	L[ R[ cnt + 4 ] = cnt + 1 ] = cnt + 4;
	head[ x ][ y ][ k ] = cnt + 1;
	insert( ( x - 1 ) * 9 + y, cnt + 1 );
	insert( 81 + ( x - 1 ) * 9 + k, cnt + 2 );
	insert( 162 + ( y - 1 ) * 9 + k, cnt + 3 );
	insert( 243 + getpos( x, y ) * 9 + k, cnt + 4 );
	cnt += 4;
}

inline void remove(int c)
{
	L[ R[ c ] ] = L[ c ];
	R[ L[ c ] ] = R[ c ];
	for( int i = D[ c ] ; i ^ c ; i = D[ i ] )
		for( int j = R[ i ] ; j ^ i ; j = R[ j ] )
		{
			U[ D[ j ] ] = U[ j ];
			D[ U[ j ] ] = D[ j ];
			S[ Col[ j ] ]--;
		}
}

inline void resume(int c)
{
	for( int i = U[ c ] ; i ^ c ; i = U[ i ] )
		for( int j = L[ i ] ; j ^ i ; j = L[ j ] )
		{
			U[ D[ j ] ] = D[ U[ j ] ] = j;
			S[ Col[ j ] ]++;
		}
	L[ R[ c ] ] = R[ L[ c ] ] = c;
}

inline bool dfs(int dep)
{
	if( dep > 81 ) return true;
	int c, mn = INF;
	for( int i = R[ 0 ] ; i ; i = R[ i ] )
		if( !S[ i ] ) return false;
		else if( S[ i ] < mn ) mn = S[ i ], c = i;
	remove( c );
	for( int i = D[ c ] ; i ^ c ; i = D[ i ] )
	{
		int tmp = pos[ i ];
		mp[ tmp / 100 ][ tmp / 10 % 10 ] = tmp % 10;
		for( int j = R[ i ] ; j ^ i ; j = R[ j ] )
			remove( Col[ j ] );
		if( dfs( dep + 1 ) ) return true;
		for( int j = L[ i ] ; j ^ i ; j = L[ j ] )
			resume( Col[ j ] );
	}
	resume( c );
	return false;
}

int main()
{
	while( true )
	{
		scanf( "%s", ch + 1 );
		if( ch[ 1 ] == 'e' ) return 0;
		cnt = 0;
		for( int i = 1 ; i <= 9 ; i++ )
			for( int j = 1 ; j <= 9 ; j++ )
			{
				if( ch[ ++cnt ] == '.' ) mp[ i ][ j ] = 0;
				else mp[ i ][ j ] = ch[ cnt ] - '0';
			}
		init();
		for( int i = 1 ; i <= 9 ; i++ )
			for( int j = 1 ; j <= 9 ; j++ )
			{
				if( mp[ i ][ j ] )
					ins( i, j, mp[ i ][ j ] );
				else
					for( int k = 1 ; k <= 9 ; k++ )
						ins( i, j, k );
			}
		int k = 0;
		for( int i = 1 ; i <= 9 ; i++ )
			for( int j = 1 ; j <= 9 ; j++ )
				if( mp[ i ][ j ] )
				{
					k++;
					int x = head[ i ][ j ][ mp[ i ][ j ] ];
					remove( Col[ x ] );
					for( int u = R[ x ] ; u ^ x ; u = R[ u ] )
						remove( Col[ u ] );
				}
		dfs( k + 1 );
		/*for( int i = 1 ; i <= 9 ; i++, putchar( 10 ) )
		{
			for( int j = 1 ; j <= 9 ; j++ )
			{
				putchar( mp[ i ][ j ] + '0' );
				if( j % 3 == 0 )
					putchar( ' ' );
			}
			if( i % 3 == 0 ) putchar( 10 );
		}*/
		for( int i = 1 ; i <= 9 ; i++ )
			for( int j = 1 ; j <= 9 ; j++ )
				putchar( mp[ i ][ j ] + '0' );
		putchar( 10 );
	}
}


你可能感兴趣的:(Poj 3074: Sudoku)