迅雷一道上机题: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表示空白。  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值