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