HDU 1180诡异的楼梯

       链接:http://acm.hdu.edu.cn/showproblem.php?pid=1180

      这道题做了好久,好几天了,终于算是过了,哎,菜鸟的我越来越。。。。

      这个楼梯是可以转动的,每分钟变一次方向,所以要考虑的是走到楼梯前的时候楼梯所处的状态到底能不能过楼梯,很显然这道题BFS比较容易,但是这个楼梯的状态,真的是绕死我了,一直卡在这好几天,找学长帮我看,告诉我楼梯状态考虑错了,改了之后才过。

     楼梯状态判断:

bool floor(point cur,char x,int i)   //判断是否等楼梯
{  
	cur.time+=1;    
	if(x=='|')  
	{        
		if((i%2==0 && cur.time%2==0)||(i%2==1&&cur.time%2==1)) 
			return 1;  
	
	     return 0;    
	} 
	else if(x=='-')  
	{          
		if((i%2==1 && cur.time%2==0)||(i%2==0&&cur.time%2==1))
			return 1; 
		
		return 0;     
	}  
}  


 

代码:

#include<cstdio>
#include<cstring>
#include<queue>

using std::queue;

int visit[22][22];
int n,m;
char map[22][22];
int dir[4][2]={0,1,1,0,0,-1,-1,0};
struct point
{
	int x,y,time;
}start;

bool floor(point cur,char x,int i)   //判断是否等楼梯
{  
	cur.time+=1;    
	if(x=='|')  
	{        
		if((i%2==0 && cur.time%2==0)||(i%2==1&&cur.time%2==1)) 
			return 1;  
	
	     return 0;    
	} 
	else if(x=='-')  
	{          
		if((i%2==1 && cur.time%2==0)||(i%2==0&&cur.time%2==1))
			return 1; 
		
		return 0;     
	}  
}  



int BFS(int a,int b)
{
	int i;
	queue<point> q;
	point cur,next;

	memset(visit,0,sizeof(visit));
	start.x=a;
	start.y=b;
	start.time=0;

	q.push(start);

	while(!q.empty())
	{
		cur=q.front();
		q.pop();

		if(map[cur.x][cur.y]=='T')
			return cur.time;
		for(i=0;i<n;i++)
		{
			next.x=cur.x+dir[i][0];
			next.y=cur.y+dir[i][1];

			if(next.x>=0&&next.x<n&&next.y>=0&&next.y<m&&!visit[next.x][next.y]&&map[next.x][next.y]!='*')
			{
				if(map[next.x][next.y]=='.'||map[next.x][next.y]=='T')
				{
					visit[next.x][next.y]=1;
					next.time=cur.time+1;
					q.push(next);
				}

				else
				{
					int dx=next.x+dir[i][0];
					int dy=next.y+dir[i][1];

                                    if(dx>=0&&dx<n&&dy>=0&&dy<m&&!visit[dx][dy]&&map[dx][dy]!='*')//确保楼梯对面没被访问过
					{
						if(floor(cur,map[next.x][next.y],i))
						{
							next.x+=dir[i][0];
							next.y+=dir[i][1];
							next.time=cur.time+1;
							visit[next.x][next.y]=1;
							q.push(next);
						}
						
						else
						{
							next.x=cur.x;
							next.y=cur.y;
							next.time=cur.time+1;
							q.push(next);
						}
					}
				}
			}
		}
	}
	return -1;
}

int main()
{
	int si,sj,i,j;

	while(scanf("%d%d",&n,&m)!=EOF)
	{
		getchar();

		for(i=0;i<n;i++)
		{
			for(j=0;j<m;j++)
			{
				scanf("%c",&map[i][j]);

			    if(map[i][j]=='S')
				{
					si=i;
					sj=j;
				}
			}
		   getchar();
		}

		map[si][sj]='*';
		printf("%d\n",BFS(si,sj));
	}
	return 0;
}



			

		
	


     还有一个学长写的代码,用了一个三维数组来记录楼梯状态,也贴下代码吧。

    代码:

#pragma warning(disable:4996)
#include <cstdio>
#include <queue>
#include <cstring>
using std::queue;
struct Node{
    int r, c, t;
};
char map[22][22];
const int dir[4][2] = { 0, 1, 1, 0, 0, -1, -1, 0 };
int m, n, dis[22][22][2], sr, sc;
int BFS(){
    memset(dis, 0x3f, sizeof(dis));
    queue<Node> que;
    Node curNode, nextNode;
    curNode.r = sr;
    curNode.c = sc;
    curNode.t = 0;
    dis[curNode.r][curNode.c][0] = 0;
    que.push(curNode);
    while (!que.empty()){
        curNode = que.front();
        que.pop();
        for (int i = 0; i < 4; i++){
            nextNode.r = curNode.r + dir[i][0];
            nextNode.c = curNode.c + dir[i][1];
            nextNode.t = curNode.t + 1;
            if (map[nextNode.r][nextNode.c] == '-' || map[nextNode.r][nextNode.c] == '|'){
                if (curNode.t % 2 == (i + (map[nextNode.r][nextNode.c] == '|')) % 2 
                    && map[nextNode.r + dir[i][0]][nextNode.c + dir[i][1]] != '*'){
                    nextNode.r += dir[i][0];
                    nextNode.c += dir[i][1];
                }
                else{
                    nextNode.r -= dir[i][0];
                    nextNode.c -= dir[i][1];
                }
            }
            if (map[nextNode.r][nextNode.c] == 'T')
                return nextNode.t;
            if (map[nextNode.r][nextNode.c] == '*'){
                nextNode.r -= dir[i][0];
                nextNode.c -= dir[i][1];
            }
            if (dis[nextNode.r][nextNode.c][nextNode.t % 2] > nextNode.t){
                dis[nextNode.r][nextNode.c][nextNode.t % 2] = nextNode.t;
                que.push(nextNode);
            }
        }
    }
}
int main(){
    while (~scanf("%d%d", &m, &n)){
        for (int i = 0; i <= n + 1; i++){
            map[0][i] = map[m + 1][i] = '*';
        }
        for (int i = 0; i <= m + 1; i++){
            map[i][0] = map[i][n + 1] = '*';
        }
        for (int i = 1; i <= m; i++){
            getchar();
            for (int j = 1; j <= n; j++){
                scanf("%c", &map[i][j]);
                if (map[i][j] == 'S'){
                    sr = i; sc = j;
                }
            }
        }
        printf("%d\n", BFS());
    }
    return 0;
}


 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值