zoukankan      html  css  js  c++  java
  • hdu 1728(搜索)

    逃离迷宫

    Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 22233    Accepted Submission(s): 5413


    Problem Description
       给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有些地方是障碍, 她必须绕行,从迷宫的一个位置,只能走到与它相邻的4个位置中,当然在行走过程中,gloria不能走到迷宫外面去。令人头痛的是,gloria是个没什 么方向感的人,因此,她在行走过程中,不能转太多弯了,否则她会晕倒的。我们假定给定的两个位置都是空地,初始时,gloria所面向的方向未定,她可以 选择4个方向的任何一个出发,而不算成一次转弯。gloria能从一个位置走到另外一个位置吗?
     
    Input
      第1行为一个整数t (1 ≤ t ≤ 100),表示测试数据的个数,接下来为t组测试数据,每组测试数据中,
      第1行为两个整数m, n (1 ≤ m, n ≤ 100),分别表示迷宫的行数和列数,接下来m行,每行包括n个字符,其中字符'.'表示该位置为空地,字符'*'表示该位置为障碍,输入数据中只有这两种字符,每组测试数据的最后一行为5个整数k, x1, y1, x2, y2 (1 ≤ k ≤ 10, 1 ≤ x1, x2 ≤ n, 1 ≤ y1, y2 ≤ m),其中k表示gloria最多能转的弯数,(x1, y1), (x2, y2)表示两个位置,其中x1,x2对应列,y1, y2对应行。
     
    Output
      每组测试数据对应为一行,若gloria能从一个位置走到另外一个位置,输出“yes”,否则输出“no”。
     
    Sample Input
    2 5 5 ...** *.**. ..... ..... *.... 1 1 1 1 3 5 5 ...** *.**. ..... ..... *.... 2 1 1 1 3
     
    Sample Output
    no yes
     
    Source
     
    限制了转弯次数不限制步数的搜索,所以当走到某个点时一直往它原来的方向走到底就行了。注意这个题输入的是 列 行 。。被坑了很多次才AC。
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<math.h>
    #include<queue>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    char graph[105][105];
    int n,m,cnt;
    struct Node{
        int x,y;
        int step;
    };
    Node s,t;
    bool vis[105][105];
    bool check(int x,int y){
        if(x<0||x>=m||y<0||y>=n||graph[x][y]=='*') return false;
        return true;
    }
    int dir[][2] = {{1,0},{-1,0},{0,1},{0,-1}};
    bool bfs(){
        memset(vis,false,sizeof(vis));
        queue<Node> q;
        q.push(s);
        vis[s.x][s.y] = true;
        s.step = 0;
        while(!q.empty()){
            Node now = q.front();
            q.pop();
            if(now.step>cnt) return false;
            if(now.x==t.x&&now.y==t.y) return true;
            Node next;
            for(int i=0;i<4;i++){
                next.x = now.x+dir[i][0];
                next.y = now.y+dir[i][1];
                next.step = now.step+1;
                while(check(next.x,next.y)){
                    if(next.x==t.x&&next.y==t.y) return true;
                    if(vis[next.x][next.y]==false){ ///没访问过进入队列
                        vis[next.x][next.y]=true;
                        q.push(next);
                    }
                    next.x+=dir[i][0]; ///笔直走向下一个点
                    next.y+=dir[i][1];
                }
    
            }
        }
        return false;
    }
    int main()
    {
        int tcase;
        scanf("%d",&tcase);
        while(tcase--){
            scanf("%d%d",&m,&n);
            for(int i=0;i<m;i++){
                scanf("%s",&graph[i]);
            }
            scanf("%d%d%d%d%d",&cnt,&s.y,&s.x,&t.y,&t.x); ///莫名的坑
            s.x-=1,s.y-=1,t.x-=1,t.y-=1;
            bool flag = bfs();
            if(flag) printf("yes
    ");
            else printf("no
    ");
        }
        return 0;
    }

     还有一种解法比较好理解,标记每次的方向,vis数组加一维.

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    using namespace std;
    const int N = 150;
    int n,m;
    int x1,y11,x2,y2,k;
    char graph[N][N];
    struct Node{
        int x,y,step,dir;
    };
    bool vis[N][N][5];
    int dir[][2] = {{-1,0},{1,0},{0,1},{0,-1}};
    bool check(int x,int y,int i){
        if(x<1||x>n||y<1||y>m||vis[x][y][i]||graph[x][y]=='*') return false;
        return true;
    }
    void bfs(){
        memset(vis,false,sizeof(vis));
        Node s;
        s.x = x1,s.y = y11,s.step = 0,s.dir = -1;
        if(graph[s.x][s.y]=='*'||graph[x2][y2]=='*'){
            printf("no
    ");
            return;
        }
        queue <Node> q;
        q.push(s);
        while(!q.empty()){
            Node now = q.front();
            q.pop();
            if(now.step>k){
                printf("no
    ");
                return;
            }
            if(now.x==x2&&now.y==y2){
                printf("yes
    ");
                return;
            }
            Node next;
            for(int i=0;i<4;i++){
                next.x = now.x + dir[i][0];
                next.y = now.y + dir[i][1];
                next.step = now.step;
                next.dir = i;
                if(now.dir!=-1&&now.dir!=next.dir){
                   next.step = now.step+1;
                }
                while(check(next.x,next.y,i)){
                    vis[now.x][now.y][i]  = true;
                    vis[next.x][next.y][i] = true;
                    q.push(next);
                    next.x = next.x + dir[i][0];
                    next.y = next.y + dir[i][1];
                    next.dir = i;
                    next.step = next.step;
                }
            }
        }
        printf("no
    ");
    }
    int main()
    {
        int tcase;
        scanf("%d",&tcase);
        while(tcase--){
            scanf("%d%d",&n,&m);
            memset(graph,0,sizeof(graph));
            for(int i=1;i<=n;i++){
                scanf("%s",graph[i]+1);
            }
            scanf("%d%d%d%d%d",&k,&y11,&x1,&y2,&x2);
            bfs();
        }
        return 0;
    }
  • 相关阅读:
    Oracle资源管理器介绍(一)
    Pfile VS Spfile (MOS Note 249664.1)
    shell不能执行su 后的脚本
    Oracle 11g 新特性之Highly Available IP(HAIP)
    Oracle 11g新特性延迟段创建和truncate的增强
    Oracle 11g RAC停止和启动步骤
    测试Oracle 11gr2 RAC 非归档模式下,offline drop数据文件后的数据库的停止与启动测试全过程
    3.OGG函数
    4.3 高级特性(3) -- 过滤
    4.2 高级特性(2) -加密
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5573340.html
Copyright © 2011-2022 走看看