uva 705 - Slash Maze

方法一(放大两倍):

for(j=0;j<w;j++)
if(s[j]=='\\') mat[2*i][2*j]=mat[2*i+1][2*j+1]=1;
else mat[2*i+1][2*j]=mat[2*i][2*j+1]=1;

把下图放大两倍。


得到以下表格。

@表示有斜线,空白处表示无斜线。

染色部分表示路径。

结合另外一位大牛的题解来看。

另外,考虑这点可不可以往右下走,只需考虑右下那个点可不可以左上走。

所以,左上,右上,左下,右下。四个方向可以缩减为两个方向。只需考虑这两种情况即可。

点击打开链接


有了上面的表格。考虑斜走就容易了。

方法二(三倍法):

放大三倍后,发现

绿色格子数目为三倍前的三倍。

因此只需

if(n)printf("%d Cycles; the longest has length %d.\n",n,max_len/3);

输出max_len/3即可。


附上代码:

一:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
const int maxn=160;
int mat[maxn][maxn];
bool vis[maxn][maxn],flag;
char s[maxn/2];
int len,w,h;
int dir[8][2]={{-1,0},{1,0},{0,-1},{0,1},{-1,-1},{-1,1},{1,-1},{1,1}};

void dfs(int i,int j)
{
	vis[i][j]=true;
	if(i==0 || j==0 || i==2*h-1 || j==2*w-1)
		flag=false;
	len++;
	int m,n;
	for(int k=0;k<8;k++)
	{
		int nx=i+dir[k][0];
		int ny=j+dir[k][1];
		if(nx>=0 && nx<2*h && ny>=0 && ny<2*w
		   &&!mat[nx][ny] && !vis[nx][ny])
		{
			if(k<4) dfs(nx,ny);
			else
			{
				if(k==4 || k==7)
				{
					if(k==4)
					{
						m=i;
						n=j;
					}
					else
					{
						m=nx;
						n=ny;
					}
					if((mat[m-1][n] && mat[m][n-1]) && //左上 
				  (!(m&1) && n&1 && mat[m-2][n-1] && mat[m+1][n]|| 
	               m&1 && !(n&1) && mat[m-1][n-2] && mat[m][n+1])) 
	                 dfs(nx,ny);
				}
		    	if(k==5 || k==6)
				{
					if(k==5)
					{
						m=i;
						n=j;
					}
					else
					{
						m=nx;
						n=ny;
					}
					if((mat[m-1][n] && mat[m][n+1]) && //右上 
				  (m&1 && n&1 && mat[m][n-1] && mat[m-1][n+2] || 
				  !(m&1) && !(n&1) && mat[m-2][n+1] && mat[m+1][n]))
				  		dfs(nx,ny);
				}
			}
		}
	}
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("705.txt","r",stdin);
#endif
	int t=0;
	while(scanf("%d%d",&w,&h)==2 && w)
	{
		memset(mat,0,sizeof(mat));
		memset(vis,false,sizeof(vis));
		int i,j;
		for(i=0;i<h;i++)
		{
			scanf("%s",s);
			for(j=0;j<w;j++)
				if(s[j]=='\\') mat[2*i][2*j]=mat[2*i+1][2*j+1]=1;
				else mat[2*i+1][2*j]=mat[2*i][2*j+1]=1;
		}
		/*for(i=0;i<2*h;i++)
		{
		  for(j=0;j<2*w;j++)
		    printf("%d",mat[i][j]);
  		  printf("\n");
		}*/
		int max_len=0,n=0;
		for(i=0;i<2*h;i++)
		  for(j=0;j<2*w;j++)
		    if(!mat[i][j] && !vis[i][j])
		    {
    			flag=true;
    			len=0;
    			dfs(i,j);
    			if(flag)
    			{
    				n++;
    				if(max_len<len) max_len=len;
    			}
		    }
    	printf("Maze #%d:\n",++t);
    	if(n)printf("%d Cycles; the longest has length %d.\n",n,max_len);
    	else printf("There are no cycles.\n");
    	printf("\n");
	//	printf("%d %d\n",w,h); 
	}
    return 0;
}

二:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
const int maxn=240;
int mat[maxn][maxn];
bool vis[maxn][maxn],flag;
char s[maxn/2];
int len,w,h;
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};

void dfs(int i,int j)
{
	if(mat[i][j] || vis[i][j]) return;
	if(i<=0 || j<=0 || i>=3*h-1 || j>=3*w-)
	{
		flag=false;
		return;
	}
	vis[i][j]=true;
	len++;
	for(int k=0;k<4;k++)
		dfs(i+dir[k][0],j+dir[k][1]);
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("705.txt","r",stdin);
    //freopen("2.txt","w",stdout);
#endif
	int t=0;
	while(scanf("%d%d",&w,&h)==2 && w)
	{
		memset(mat,0,sizeof(mat));
		memset(vis,false,sizeof(vis));
		int i,j;
		for(i=0;i<h;i++)
		{
			scanf("%s",s);
			for(j=0;j<w;j++)
				if(s[j]=='\\') mat[3*i][3*j]=mat[3*i+1][3*j+1]=mat[3*i+2][3*j+2]=1;
				else mat[3*i+2][3*j]=mat[3*i+1][3*j+1]=mat[3*i][3*j+2]=1;
		}
		/*for(i=0;i<3*h;i++)
		{
		  for(j=0;j<3*w;j++)
		    printf("%d",mat[i][j]);
  		  printf("\n");
		}*/
		int max_len=0,n=0;
		for(i=0;i<3*h;i++)
		  for(j=0;j<3*w;j++)
		    if(!mat[i][j] && !vis[i][j])
		    {
    			flag=true;
    			len=0;
    			dfs(i,j);
    			if(flag)
    			{
    				n++;
    				if(max_len<len) max_len=len;
    			}
		    }
    	printf("Maze #%d:\n",++t);
    	if(n)printf("%d Cycles; the longest has length %d.\n",n,max_len/3);
    	else printf("There are no cycles.\n");
    	printf("\n");
	//	printf("%d %d\n",w,h); 
	}
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值