题目描述:
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表示空白。