您的位置:首页 > 其它

uva 705 Slash Maze

2012-11-16 23:41 337 查看
近期所做题目中最好的一道,首先是比较创新不是常规的,另外需要比较好的数学功底能够洞察到一些小细节,然后转化方法貌似有很多,我自己想了很多但是都很差劲,最后实在没办法很无耻地找了解题报告,这篇解题报告感觉写得最好,我就是按照他的思路自己写的代码1A,佩服佩服此大神

解题报告 http://hi.baidu.com/lixubd/item/1fbebd2c0389700f43634a5f

算法思路都在里面了,我就不写了,我自己独立写了代码,加了很多注释,代码虽然比较多(这道题代码本来就多),然后其实不难读懂

说明一点,预处理后的矩阵行和列都翻倍了,我的代码行和列都是从1开始标号的,而那位大神的代码都是从0开始标号的,不同

有一点这里说明一下,水平和垂直的上下左右移动没什么问题,直接递归搜索就好

但是,但是,但是,就是斜向移动,左上,右上,左下,右下,四个方向,每个方向都是有两种情况,也就是有8个情况了,8中情况对当前点的横纵坐标是有要求的,有的情况要求横坐标为奇数纵坐标为偶数,有的要求横坐标偶数纵坐标奇数,有的要求横纵都是奇数,有的要求横纵都是偶数,总之这8个人情况对当前点的横纵坐标的奇偶性的要求是不同,每种情况都需要独立判断,不是统一的,至于没什么,其实只要画图出来就可以了,这里不说明白

提示一下,原始矩阵是n*m(行*列),一个格子输入一个斜杆,然后这个矩阵翻倍变成2n*2m,再对应一下这8中情况当前点的位置,是在偶数行呢还是奇数行呢?是在奇数列呢还是偶数列呢?然后就明白了哈哈哈哈

#include <cstdio>
#include <cstring>
#define MAX 160  //长宽最多为75,翻倍为150
bool g[MAX][MAX];
bool vis[MAX][MAX];
int n,m;  //原始长宽
int dd[9][2]={{0,0},{-1,0},{1,0},{0,-1},{0,1},{-1,-1},{-1,1},{1,-1},{1,1}};
//12345678表示八个方向,上下左右,左上,右上,左下,右下;
int max,ccount,c,FIND;
void input()
{
memset(g,0,sizeof(g));
memset(vis,0,sizeof(vis));
for(int i=0; i<=2*m+1; i++)  //翻倍后的迷宫的上下外围不能访问
g[0][i]=g[2*n+1][i]=1;
for(int i=0; i<=2*n+1; i++)  //翻倍后的迷宫的左右外围不能访问
g[i][0]=g[i][2*m+1]=1;
for(int i=1; i<=n; i++)  //原始迷宫的i行
{
char s[MAX];
scanf("%s",s+1);
for(int j=1; j<=m; j++)
if(s[j]=='/')
{
g[2*i][(2*j)-1]=1;
g[(2*i)-1][2*j]=1;
}
else
{
g[2*i][2*j]=1;
g[(2*i)-1][(2*j)-1]=1;
}
}
/*
for(int i=1; i<=2*n; i++)
{
for(int j=1; j<=2*m; j++)
printf("%d ",g[i][j]);
printf("\n");
}
*/
return ;
}

void dfs(int x ,int y)
{
vis[x][y]=1;
c++;//格子数计数
if(x==1 || x==2*n || y==1 || y==2*m) FIND=0;
//如果成环的话,一定不会到达矩阵的边界,因为一定有斜杆包围起来的,到了边界不可能有斜杆包围
//虽然不是环但是不能就此返回,一定要把这个连通分量全部搜索完,仅仅是改变FIND表示这个连通分量不是一个环

for(int i=1; i<=8; i++)  //枚举8个可能的方向
{
int xx,yy;  //将要移向的格子的坐标
xx=x+dd[i][0];
yy=y+dd[i][1];
if(!g[xx][yy] && !vis[xx][yy])  //新格子是可以到达的,而且没有被访问过的
{
if(i<=4)  //前四个方向是上下左右,不需要做什么特殊判断,直接递归
dfs(xx,yy);
else    //斜方向
{
if(i==5) //左上
{
if( (g[x][y-1]&&g[x-1][y-2])&& (g[x][y+1]&&g[x-1][y])&& !(x&1)&&(y&1) ||
(g[x-1][y]&&g[x-2][y-1])&& (g[x+1][y]&&g[x][y-1])&& (x&1)&&!(y&1) )
dfs(xx,yy);
}
else if(i==6)  //右上
{
if((g[x][y-1]&&g[x-1][y])&& (g[x][y+1]&&g[x-1][y+2])&& !(x&1)&&!(y&1) ||
(g[x-1][y]&&g[x-2][y+1])&& (g[x+1][y]&&g[x][y+1])&& (x&1)&&(y&1) )
dfs(xx,yy);
}
else if(i==7) //左下
{
if( (g[x][y-1]&&g[x+1][y-2])&& (g[x][y+1]&&g[x+1][y])&& (x&1)&&(y&1)||
(g[x][y-1]&&g[x-1][y])&& (g[x+1][y]&&g[x+2][y-1])&& !(x&1)&&!(y&1))
dfs(xx,yy);
}
else   //右下
{
if( (g[x][y-1]&&g[x+1][y])&& (g[x][y+1]&&g[x+1][y+2])&& (x&1)&& !(y&1) ||
(g[x-1][y]&&g[x][y+1])&& (g[x+1][y]&&g[x+2][y+1])&& !(x&1)&& (y&1) )
dfs(xx,yy);
}
}
}
}

return ;
}

void solve()
{
//dfs,每次搜索其实都搜完了一个连通分量,其实等同于图的遍历
max=ccount=0;
for(int i=1; i<=2*n; i++)
for(int j=1; j<2*m; j++)
if(!g[i][j])
if(!vis[i][j])
{
c=0;
FIND=1;
dfs(i,j);
if(FIND)
{
ccount++;
if(c>max) max=c;
}
}
return ;
}
int main()
{
int T=0;
while(scanf("%d%d",&m,&n) && n && m)  //先宽再长
{
input();
solve();
T++;
printf("Maze #%d:\n",T);
if(!ccount)
printf("There are no cycles.\n");
else
printf("%d Cycles; the longest has length %d.\n",ccount,max);
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: