能否在指定时间恰好到达一点-dfs

483: qtech系列故事之——北京奇遇记

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 32   Solved: 3
[ Submit][ Status][ Web Board]

Description

在美丽的qtech,有一个传奇的人物,被叫做671coder,大家都亲切的称呼他为“耀哥”。耀哥现在大四了,作为一个ACMer,大学期间是木有什么项目经验的,所以耀哥就一直在苦逼寒酸的找工作。。。

一天耀哥在去北邮的路上,看到了一个瓶子,耀哥心想:垃圾怎么能随地乱扔呢,于是就捡了起来。拿起来之后,发现这个瓶盖子很独特,便打开了看看。谁知道!这一打开不要紧!眼前突然出现了一个巨人!巨人说:“我是瓶子神,我可以给你一个迷宫,给你一个限定时间,如果你能在规定时间恰好走到指定终点,我就会给你一个年薪100woffer,如果你感觉我给你的迷宫不能在规定时间恰好走到终点,你可以选择找我换一个迷宫,当然,只要你决定了就无法更改。”(当然由于耀哥腿脚不是太灵便,1s只能走一格)

耀哥想了想:自己好歹大学期间也是搞acm的,迷宫什么的能难道我么?于是他淡定的说:“来吧!迷宫拿来!”于是巨人就把迷宫给了耀哥。

聪明的你,作为一个ACMer,请帮耀哥计算一下他是需要找巨人换迷宫呢?还是勇敢的走下去这个迷宫呢?

Input

输入第一行包含三个数据N,M,T, N代表迷宫的长度;M代表迷宫的宽度;T代表给的规定时间。当NMT都为0的时候输入结束。(1 < N, M < 7; 0 < T < 50)

接下来就是一个迷宫,’S’表示耀哥的起始位置;’D’表示迷宫的出口;’.’表示这里是空地,可以走;’X’则表示这里是墙,不能经过。

Output

  如果耀哥能在限定时间内,顺利走到终点,请输出”Get it!”,否则需要找到巨人换,请输出”Change it!”

Sample Input

4 4 5
S.X.
. .X.
..XD
....
3 4 5
S.X
.. .
X..
. .D
0 0 0

Sample Output

Change it!
Get it!


这个一开始以为是简单的DFS遍历,后来仔细一想,他让的是恰好到达而不是在求最路径,这个一下就坑了
所以只能用优先队列,然后开了一个四维的数组d[x][y][i][s]记录在x,y坐标上方向为i的目前步数状态为s
的节点是否访问过
简直累死了!
#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<string.h>
#include<stdlib.h>
using namespace std;
#define MAX_SIZE 50 + 10
/*多状态的BFS统计*/
int visa[MAX_SIZE][MAX_SIZE][4][55];
int dist[MAX_SIZE][MAX_SIZE][4];/*表示在x,y坐标方向为z的是否被遍历过*/
int N,M,T;
int dir1[4]={1,-1,0,0};
int dir2[4]={0,0,-1,1};
int start_x,start_y;
int end_x,end_y;
char maps[MAX_SIZE][MAX_SIZE];
struct step /*这个表示每一个点的状态*/{
    int x;
    int y;
    int dist;/*表示从起点走到这一步花的歩数*/
    friend bool operator < (const step &a, const step &b){ // 重载<构建最小堆
        return a.dist > b.dist;
    }
};
struct step start,p1,p2;
void find_start_end()
{
    int ok1=0;
    int ok2=0;
    for(int i=0;i<N;i++){
         for(int j=0;j<M;j++){
          if(maps[i][j]=='S'){
              start_x=i;
              start_y=j;
          }
          if(maps[i][j]=='D'){
              end_x=i;
              end_y=j;
          }
          if(ok1&&ok2) return;
       }
     }
}
void dfs()
{
    priority_queue<step>S;
    int ok=1;
    while(!S.empty())
        S.pop();
    /*初始化*/
    start.x=start_x;
    start.y=start_y;
    start.dist=0;
    /*初始化起点*/
    S.push(start);/*加入到队列里面*/
    while(!S.empty())
    {
        int nx,ny;
        p1=S.top();/*从顶部拿取元素*/
        S.pop();
        //printf("(%d,%d,%d)\n",p1.x,p1.y,p1.dist);
        for(int i=0;i<4;i++)
        {
            nx=p1.x+dir1[i];
            ny=p1.y+dir2[i];
            /*如果这个点没有越界并且是一个可走路
            并且方向没有走过*/
            if((nx>=0&&ny>=0&&nx<N&&ny<M&&!visa[nx][ny][i][p1.dist+1]&&maps[nx][ny]!='X'))
            {
                visa[nx][ny][i][p1.dist+1]=1;
                p2.x=nx;
                p2.y=ny;
                dist[nx][ny][i]=p1.dist+1;
                p2.dist=dist[nx][ny][i];
                //printf("(%d %d %d)->(%d,%d,%d)\n",p1.x,p1.y,p1.dist,p2.x,p2.y,p2.dist);
                S.push(p2);
                if(nx==end_x&&ny==end_y&&p2.dist==T)
                {
                    printf("Get it!\n");
                    ok=0;
                    break;
                }
            }
        }
        if(!ok) break;
    }
    if(ok)
    printf("Change it!\n");
}
int main(){
    for(;scanf("%d%d%d%*c",&N,&M,&T);){
        memset(visa,0,sizeof(visa));
        memset(dist,0,sizeof(dist));
        if(!N&&!M&&!T) break;
        for(int i=0;i<N;i++)/*输入迷宫!*/
        gets(maps[i]);
        find_start_end();
        /*找到迷宫的起始和结束点*/
        dfs();
        /*开始进行遍历*/
    }
    return 0;
}


Sample Output

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值