迅雷一道上機題:nxn的方格,去掉一條對角線的兩個對角...

題目描述:

nxn的方格,去掉一條對角線的兩個對角,餘下部分用面積爲2的矩形覆蓋,即1x2或2x1的矩形,結果是不可能完全覆蓋,請編程枚舉所有的覆蓋情況 。


算法描述:

這是迅雷一道機試題,在網上被反覆引用。用到的方法也比較簡單,就是回溯法,所以沒有大神花時間去實現,網上都沒有實現的代碼。我用C語言實現了一版,在3×3時答案正確,4×4時有194個解。正確性有待驗證,希望大家看到了實現了可以把答案和我交流下。我先拋磚引玉了。

代碼:

/*
 *nxn的方格,去掉一條對角線的兩個對角,餘下部分用面積爲2的矩形覆蓋,即1x2或2x1的矩形,結果是不可能完全覆蓋,請編程枚舉所有的覆蓋情況 
 * */

#include<stdio.h>
#define N 4

int maze[N][N];
const char dirs[] = {'^','v','<','>','O','#',0};
enum enum_dir{
	up,down,left,right,unused,block,unvisited
};
int result_num = 0;

int find_another(int x,int y);
int set_pos_dir(int x,int y,int dir);
int get_partner(int x,int y,int dir);
int get_next_node(int * nx,int *ny);
void print_maze();
void print_result();
int tell_can_unused(int x,int y);

int main()
{
	//init
	maze[0][0] = dirs[block];
	maze[N-1][N-1] = dirs[block];

	//find cover case
	find_another(0,1);
}

int find_another(int x,int y)
{
	//deal with x,y
	int i;
	for(i=up;i<=right;i++){
		if(1 == get_partner(x,y,i) ){
			int par_x,par_y,par_dir;
			switch(i){
				case up:
					par_x = x-1; par_y = y; par_dir = down;
					break;
				case down:
					par_x = x+1; par_y = y; par_dir = up;
					break;
				case left:
					par_x = x; par_y = y-1; par_dir = right;
					break;
				case right:
					par_x = x; par_y = y+1; par_dir = left;
					break;
			}

			set_pos_dir(x,y,i); 
			set_pos_dir(par_x,par_y,par_dir);
			
			int next_x,next_y;
			if(1==get_next_node(&next_x,&next_y) ){
				find_another(next_x,next_y);	
			}else{
				//no next node,the end 
				print_result();
			}		

			set_pos_dir(x,y,unvisited); 
			set_pos_dir(par_x,par_y,unvisited);
		}
	}

	//whether the node can be  an unused node
	if(0 == tell_can_unused(x,y))
		return 0;

	set_pos_dir(x,y,unused);
	int next_x,next_y;
	if(1==get_next_node(&next_x,&next_y) ){
		find_another(next_x,next_y);	
	}else{
		//no next node,the end 
		print_result();
	}		
	set_pos_dir(x,y,unvisited);

	return 0;
}

//1==can  0==can't
int tell_can_unused(int x,int y)
{
	if(x>0 && (maze[x-1][y]==dirs[unused] ))
		return 0;
	if(x<N-1 && (maze[x+1][y]==dirs[unused] ))
		return 0;
	if(y>0 && (maze[x][y-1]==dirs[unused] ))
		return 0;
	if(y<N-1 && (maze[x][y+1]==dirs[unused] )) 
		return 0;
	return 1;
}

void print_result()
{
	printf("case %d-------\n",++result_num);
	print_maze();
}

void print_maze()
{
	int i,j;
	for(i=0;i<N;i++){
		for(j=0;j<N;j++){
			char c = maze[i][j];
			if(c==0)
				printf("   ");
			else
				printf("%c  ",c);
		}
		printf("\n");
	}
	printf("\n");
}

//find another unvisited node 1==found 0==not found
int get_next_node(int * nx,int *ny)
{
	int i,j;
	for(i=0;i<N;i++)
		for(j=0;j<N;j++){
			if(maze[i][j] == dirs[unvisited]){
				*nx = i;
				*ny = j;
				return 1;
			}
		}

	return 0;
}

// 1==found 0==not found
int get_partner(int x,int y,int dir)
{
	switch(dir){
		case up:
			x--;
			break;
		case down:
			x++;
			break;
		case left:
			y--;
			break;
		case right:
			y++;
			break;
	}
	//out of range
	if(x<0 || x>=N || y<0 || y>=N)
		return 0;
	if(0 != maze[x][y])
		return 0;
	return 1;
}

int set_pos_dir(int x,int y,int dir)
{
	maze[x][y] = dirs[dir];
	return 0;
}

結果:

下面是3×3的結果,我用 >< 這樣相對的箭頭表示一個矩形,#表示不能填充,O表示空白。  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章