Task: Solve a Hidato puzzle

C: #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int *board, *flood, *known, top = 0, w, h;

static inline int idx(int y, int x) { return y * w + x; }

int neighbors(int c, int *p)

{
	int i, j, n = 0;
	int y = c / w, x = c % w;

	for (i = y - 1; i <= y + 1; i++) {
		if (i < 0 || i >= h) continue;
		for (j = x - 1; j <= x + 1; j++)
			if (!(j < 0 || j >= w
				|| (j == x && i == y)
				|| board[ p[n] = idx(i,j) ] == -1))
				n++;
	}

	return n;
}

void flood_fill(int c)

{
	int i, n[8], nei;

	nei = neighbors(c, n);
	for (i = 0; i < nei; i++) { 
		if (board[n[i]] || flood[n[i]]) continue; 

		flood[n[i]] = 1;
		flood_fill(n[i]);
	}
}


int check_connectity(int lowerbound)
{
	int c;
	memset(flood, 0, sizeof(flood[0]) * w * h);
	for (c = lowerbound + 1; c <= top; c++)
		if (known[c]) flood_fill(known[c]); 

	for (c = 0; c < w * h; c++)
		if (!board[c] && !flood[c]) 
			return 0;

	return 1;
}

void make_board(int x, int y, const char *s)
{
	int i;

	w = x, h = y;
        top = 0;
	x = w * h;

        known = calloc(x + 1, sizeof(int));
        board = calloc(x,     sizeof(int));
        flood = calloc(x,     sizeof(int));

	while (x--) board[x] = -1;

	for (y = 0; y < h; y++)
	for (x = 0; x < w; x++) {
		i = idx(y, x);

		while (isspace(*s)) s++;

		switch (*s) {
		case '_':	board[i] = 0;
		case '.':	break;
		default:
			known[ board[i] = strtol(s, 0, 10) ] = i;
			if (board[i] > top) top = board[i];
		}

		while (*s && !isspace(*s)) s++;
	}
}

void show_board(const char *s)
{
	int i, j, c;

	printf("\n%s:\n", s);

	for (i = 0; i < h; i++, putchar('\n'))
	for (j = 0; j < w; j++) {
		c = board[ idx(i, j) ];
		printf(!c ? " __" : c == -1 ? "   " : " %2d", c);
	}
}

int fill(int c, int n)
{
	int i, nei, p[8], ko, bo;

	if ((board[c] && board[c] != n) || (known[n] && known[n] != c))
		return 0;

	if (n == top) return 1;

	ko = known[n];
	bo = board[c];
	board[c] = n;

	if (check_connectity(n)) {
		nei = neighbors(c, p);
		for (i = 0; i < nei; i++)
			if (fill(p[i], n + 1))
				return 1;
	}

	board[c] = bo;
	known[n] = ko;
	return 0;
}

int main()
{
	make_board(
#define USE_E 0
#if (USE_E == 0)
		8,8,	" __ 33 35 __ __ .. .. .."
			" __ __ 24 22 __ .. .. .."
			" __ __ __ 21 __ __ .. .."
			" __ 26 __ 13 40 11 .. .."
			" 27 __ __ __  9 __  1 .."
			" .   . __ __ 18 __ __ .."
			" .  ..  .  . __  7 __ __"
			" .  .. .. ..  .  .  5 __"
#elif (USE_E == 1)
	3, 3,	" . 4 ."
		" _ 7 _"
		" 1 _ _"
#else
	50, 3,
	" 1 _ _ . . _ _ . . _ _ . . _ _ . . _ _ . . _ _ . . _ _ . . _ _ . . _ _ . . _ _ . . _ _ . . _ _ . . 74"
	" . . _ . _ . _ . _ . _ . _ . _ . _ . _ . _ . _ . _ . _ . _ . _ . _ . _ . _ . _ . _ . _ . _ . _ . _ ."
	" . . . _ _ . . _ _ . . _ _ . . _ _ . . _ _ . . _ _ . . _ _ . . _ _ . . _ _ . . _ _ . . _ _ . . _ _ ."
#endif
	);

	show_board("Before");
	fill(known[1], 1);
	show_board("After"); 

	return 0;
}


C++: #include <iostream>
#include <sstream>
#include <iterator>
#include <vector>


using namespace std;


struct node
{
    int val;
    unsigned char neighbors;
};

class hSolver
{
public:
    hSolver()
    {
	dx[0] = -1; dx[1] = 0; dx[2] = 1; dx[3] = -1; dx[4] = 1; dx[5] = -1; dx[6] = 0; dx[7] = 1;
	dy[0] = -1; dy[1] = -1; dy[2] = -1; dy[3] = 0; dy[4] = 0; dy[5] = 1; dy[6] = 1; dy[7] = 1;
    }

    void solve( vector<string>& puzz, int max_wid )
    {
	if( puzz.size() < 1 ) return;
	wid = max_wid; hei = static_cast<int>( puzz.size() ) / wid;
	int len = wid * hei, c = 0; max = 0;
	arr = new node[len]; memset( arr, 0, len * sizeof( node ) );
	weHave = new bool[len + 1]; memset( weHave, 0, len + 1 );
		
	for( vector<string>::iterator i = puzz.begin(); i != puzz.end(); i++ )
	{
	    if( ( *i ) == "*" ) {    arr[c++].val = -1; continue; }
	    arr[c].val = atoi( ( *i ).c_str() );
	    if( arr[c].val > 0 ) weHave[arr[c].val] = true;
	    if( max < arr[c].val ) max = arr[c].val;
	    c++;
	}

	solveIt(); c = 0;
	for( vector<string>::iterator i = puzz.begin(); i != puzz.end(); i++ )
	{
	    if( ( *i ) == "." )
	    {
		ostringstream o; o << arr[c].val;
		( *i ) = o.str();
	    }
	    c++;
	}
	delete [] arr;
	delete [] weHave;
    }

private:
    bool search( int x, int y, int w )
    {
	if( w == max ) return true;

	node* n = &arr[x + y * wid];
	n->neighbors = getNeighbors( x, y );
	if( weHave[w] )
	{
	    for( int d = 0; d < 8; d++ )
	    {
		if( n->neighbors & ( 1 << d ) )
		{
		    int a = x + dx[d], b = y + dy[d];
		    if( arr[a + b * wid].val == w )
		    if( search( a, b, w + 1 ) ) return true;
		}
	    }
	    return false;
	}

	for( int d = 0; d < 8; d++ )
	{
	    if( n->neighbors & ( 1 << d ) )
	    {
		int a = x + dx[d], b = y + dy[d];
		if( arr[a + b * wid].val == 0 )
		{
		    arr[a + b * wid].val = w;
		    if( search( a, b, w + 1 ) ) return true;
		    arr[a + b * wid].val = 0;
		}
	    }
	}
	return false;
    }

    unsigned char getNeighbors( int x, int y )
    {
	unsigned char c = 0; int m = -1, a, b;
	for( int yy = -1; yy < 2; yy++ )
	    for( int xx = -1; xx < 2; xx++ )
	    {
		if( !yy && !xx ) continue;
		m++; a = x + xx, b = y + yy;
		if( a < 0 || b < 0 || a >= wid || b >= hei ) continue;
		if( arr[a + b * wid].val > -1 ) c |= ( 1 << m );
	    }
	return c;
    }

    void solveIt()
    {
	int x, y; findStart( x, y );
	if( x < 0 ) { cout << "\nCan't find start point!\n"; return; }
	search( x, y, 2 );
    }

    void findStart( int& x, int& y )
    {
	for( int b = 0; b < hei; b++ )
	    for( int a = 0; a < wid; a++ )
		if( arr[a + wid * b].val == 1 ) { x = a; y = b; return; }
	x = y = -1;
    }

    int wid, hei, max, dx[8], dy[8];
    node* arr;
    bool* weHave;
};

int main( int argc, char* argv[] )
{
    int wid;
    string p = ". 33 35 . . * * * . . 24 22 . * * * . . . 21 . . * * . 26 . 13 40 11 * * 27 . . . 9 . 1 * * * . . 18 . . * * * * * . 7 . . * * * * * * 5 ."; wid = 8;
    
    

    istringstream iss( p ); vector<string> puzz;
    copy( istream_iterator<string>( iss ), istream_iterator<string>(), back_inserter<vector<string> >( puzz ) );
    hSolver s; s.solve( puzz, wid );

    int c = 0;
    for( vector<string>::iterator i = puzz.begin(); i != puzz.end(); i++ )
    {
	if( ( *i ) != "*" && ( *i ) != "." )
	{
	    if( atoi( ( *i ).c_str() ) < 10 ) cout << "0";
	    cout << ( *i ) << " ";
	}
	else cout << "   ";
	if( ++c >= wid ) { cout << endl; c = 0; }
    }
    cout << endl << endl;
    return system( "pause" );
}