这个题是一道非常经典的DFS,我调试了几个晚上,每天晚上调一个小时,终于调试好了。我采用了《计算机图形学》里的编码裁剪算法,再加上DFS就AC了。
效率是并列第一名(C语言)。
我的代码:
#include<stdio.h>
unsigned char farm[50][50];
unsigned char type[11]={9,12,3,6,10,5,13,11,7,14,15};//A-K 11种编码
unsigned char con[4]={7,11,13,14}; //上右下左 裁边
int der[4][2]={{-1,0},{0,1},{1,0},{0,-1}};// 上右下左 顺时针
int wid,len;
void dfs(int x,int y)
{
int i,a,b,tag1,tag2 ;
/* 先把无效边裁减掉 */
if(x == 0)
farm[x][y] &= con[0];
if(y == len - 1)
farm[x][y] &= con[1];
if(x == wid - 1)
farm[x][y] &= con[2];
if(y == 0)
farm[x][y] &= con[3];
if(farm[x][y])//如果为0,就没必要深搜了
for(i = 0 ; i < 4 ; ++i)
{
a = x + der[i][0];
b = y + der[i][1];
if(a < 0 || a >= wid || b < 0 || b >= len)//越界判断
continue ;
tag1 = 0 ;
tag2 = 0 ;
if(farm[a][b])
{
switch(i)// 判断是否能连接上
{
case 0: tag1 = farm[a][b] & 2; tag2 = farm[x][y] & 8 ;break;
case 1: tag1 = farm[a][b] & 1; tag2 = farm[x][y] & 4 ;break;
case 2: tag1 = farm[a][b] & 8; tag2 = farm[x][y] & 2 ;break;
case 3: tag1 = farm[a][b] & 4; tag2 = farm[x][y] & 1 ;break;
}
if(tag1 && tag2) //连接上了
{
switch(i)//剪掉连边
{
case 0: farm[x][y] &= con[0];farm[a][b] &= con[2];break;
case 1: farm[x][y] &= con[1];farm[a][b] &= con[3];break;
case 2: farm[x][y] &= con[2];farm[a][b] &= con[0];break;
case 3: farm[x][y] &= con[3];farm[a][b] &= con[1];break;
}
dfs(a,b);
}
}
}
farm[x][y] = 0 ; //都搜了,要置0
return ;
}
int main()
{
int i,j,cnt;
char c;
while(scanf("%d%d",&wid,&len))
{
if(wid < 0 || len < 0) break;
for(i = 0 ; i < wid ; ++i)
{
getchar();
for(j = 0 ; j < len ; ++j)
{
scanf("%c",&c);
farm[i][j] = type[c-'A'];
}
}
cnt = 0;
for(i = 0 ; i < wid ; ++i)
for(j = 0 ; j < len ; ++j)
if(farm[i][j])
{
dfs(i,j);
++cnt;
}
printf("%d\n",cnt);
}
return 0;
}
由于不太好理解,所以我写了很多注释。