HDU 3912 Turn Right(模拟)

Problem Description
This summer, ELT and his classmates went to Beijing for a training of coding. ELT have never been to Beijing before, so at the weekend, he together with some friends went to the National Museum, it's free for students!

  The National Museum consists of many parts. One part of it is an exhibition of Ancient China From Xia Dynasty to Qing Dynasty, it needs a big room to show all the things. What's more, there exist many walls to hang pictures. The boundary of this room is walls except the entrance and exit.

  With walls, an entrance and an exit, this room can be regarded as a maze. To make it simple, this room is a R*C grid, wall is constructed at some edges of grid. The entrance is always at the first row, and the exit is always at the last row, just like the picture below.

ELT can't remember his direction in maze, but he is a clever boy. He knew an algorithm called "Always Turn Right", it's procedure is as follows: at any grid of this room, if we can turn right(no wall at right side), then we must turn right; if we can't turn right but can go straight forward, then we must go forward; if we can't go forward but can turn left, then we must turn left; if we can't even turn left, we just turn backward. In the picture above, if we use this algorithm, we'll visit these grids in order: Entrance --> (0, 1) --> (0, 0) --> (0, 1) --> (0, 2) --> (1, 2) --> (1, 1) --> (1, 0) --> (2, 0) --> (1, 0) --> (1, 1) --> (2, 1) --> (2, 2) --> Exit. Very easy, doesn't it?

  ELT uses "Always Turn Right" algorithm to visit this room from entrance to exit, and then from exit to entrance. He wants to know whether he walked all grids in the room. Now ELT is dizzy because the maze is too big, can you help him?
 

Input
First line is an integer T, means T test cases. In each test case, the first line has four numbers: R, C, Ent_Column, Exit_Column. Ent_Column is the column number of entrance; Exit_Column is the column number of exit.
Then following 2*R-1 lines, 2*i line have C-1 numbers, the j-th number shows whether there is a wall between grid(i, j) and grid(i, j+1), 2*i+1 line have C numbers, the j-th number shows whether there is a wall between grid(i, j) and grid(i+1, j). Number 1 represents a wall, 0 represents no wall.
  We guarantee that there exists a path from entrance to exit.
2 <= R, C <= 500
0 <= Ent_Column, Exit_Column < C
 

Output
If ELT can walk all grids in the room, print one line "YES", otherwise, print one line "NO".
 

Sample Input
  
  
1 3 4 1 2 0 0 0 1 1 0 1 0 0 0 0 0 0 0 1 0 0
 

Sample Output
  
  
YES
 

Source

 


题意:

给出入口和出口,规定走的时候必须按照右、前、左、后的方向走

从入口走到出口,再从出口走到入口,问能不能走遍所有的格子

和一般图不一样的是,这里的每个格子都是可以走的,

但是格子与格子之间的边有可走(1)和不可走(0)两种情况

每个格子4条边,显然是要记录走的方向的

分析(吐槽):

这个被分类为BFS/DFS的题绝壁是一道非常傻逼的模拟题

然而一道模拟题被我玩了几个小时。。。

首先是读题,鶸最初木有看到题目说的是从入口走到出口再从出口走到入口。。。

傻不拉几的以为题目有问题。。。

其次是输入,开始样例过了但是没想到我的输入写的有问题。。。

最后,最近可能DFS玩多了,于是愉快的递归爆栈了。。。

MLE后直接改循环就过了。。。

思路就是单纯的模拟,每个点可以走四个方向,有墙或者走过的就标记不能走

注意最后就算到达终点也必须按题目给的方向走

然后因为鶸渣对于4个方向的四种走法直接手写的,

所以代码很丑很丑很丑很丑很丑。。。。。。丑。。。


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
const int N = 500;
int r, c;
bool vis[N + 5][N + 5][4]; //在(i,j)点朝向k是否可行&是否走过
bool ss[N + 5][N + 5][4]; //要走两遍,图要保存下
struct Node
{
    int x, y;
    int c;//在x,y点的朝向
} t;
bool ok (Node a)
{
    if (a.x >= 0 && a.y >= 0 && a.x < r && a.y < c && vis[a.x][a.y][a.c] == 0) return 1;
    else if (a.x == t.x && a.y == t.y) return 1;//到达终点,终点算是越界的。。。
    return 0;
}
Node go (Node a) //0123分别表示朝向为上下左右
{
    Node b ;
    if (a.c == 0) //朝上
    {
        b = a;b.y++;b.c = 3;//右转
        if (ok (b) ) return b;
        b = a;b.x--;b.c = 0;//直走
        if (ok (b) ) return b;
        b = a;b.y--;b.c = 2;//左转
        if (ok (b) ) return b;
        b = a;b.x++;b.c = 1;//后退
        if (ok (b) ) return b;
    }
    else if (a.c == 1) //朝下
    {
        b = a;b.y--;b.c = 2;
        if (ok (b) ) return b;
        b = a;b.x++;b.c = 1;
        if (ok (b) ) return b;
        b = a;b.y++;b.c = 3;
        if (ok (b) ) return b;
        b = a;b.x--;b.c = 0;
        if (ok (b) ) return b;
    }
    else if (a.c == 2) //朝左
    {
        b = a;b.x--;b.c = 0;
        if (ok (b) ) return b;
        b = a;b.y--;b.c = 2;
        if (ok (b) ) return b;
        b = a;b.x++;b.c = 1;
        if (ok (b) ) return b;
        b = a;b.y++;b.c = 3;
        if (ok (b) ) return b;
    }
    else if (a.c == 3) //朝右
    {
        b = a;b.x++;b.c = 1;
        if (ok (b) ) return b;
        b = a;b.y++;b.c = 3;
        if (ok (b) ) return b;
        b = a;b.x--;b.c = 0;
        if (ok (b) ) return b;
        b = a;b.y--;b.c = 2;
        if (ok (b) ) return b;
    }
    b = a;b.c = -1;
    return b;//无路可走=-=不晓得题目有没有这种情况,反正考虑下
}
bool gone[N + 5][N + 5];//最后判断是否走遍所有格子
void dfs (Node s)
{
    while (1)
    {
        if (s.c == -1) return;//无路可走
        if (s.x == t.x && s.y == t.y) return; //走到终点
//    cout<<s.x<<","<<s.y<<endl;//样例输出无误^_^
        Node nx = go (s);
        if (nx.x == t.x && nx.y == t.y) return;
        vis[nx.x][nx.y][nx.c] = 1;
        gone[nx.x][nx.y] = 1;
        s = nx;
    }
}
bool all()//判断是否走遍了所有格子
{
    for (int i = 0; i < r; ++i)
    {
        for (int j = 0; j < c; ++j)
        {
            if (!gone[i][j]) return 0;
        }
    }
    return 1;
}
int main()
{
    int T;
    scanf ("%d", &T);
    while (T--)
    {
        scanf ("%d %d", &r, &c);
        int sy, ty;
        scanf ("%d %d", &sy, &ty);
        mem (vis, 0);
        for (int i = 0; i < c; ++i)//上下边界
        {
            vis[0][i][1] = 1;
            vis[r - 1][i][0] = 1;
        }
        for (int i = 0; i < 2 * r - 1; ++i) //给出的是墙,转换成vis数组中的每个点的方向
        {
            if (i % 2 == 0) //左右
            {
                vis[i / 2][0][3] = 1;
                for (int j = 0, x; j < c - 1; ++j)
                {
                    scanf ("%d", &x);
                    vis[i / 2][j][2] = x;
                    vis[i / 2][j + 1][3] = x;
                }
                vis[i / 2][c - 1][2] = 1;
            }
            else
            {
                for (int j = 0, x; j < c; ++j)
                {
                    scanf ("%d", &x);
                    vis[i / 2][j][0] = x;
                    vis[i / 2 + 1][j][1] = x;
                }
            }
        }
        memcpy (ss, vis, sizeof (vis) );//正反走两遍,图先存起来
        Node s;s.x = 0;s.y = sy;s.c = 1;
        t.x = r;t.y = ty;//终点是越界的
        mem (gone, 0);
        dfs (s);//正着走
        memcpy (vis, ss, sizeof (vis) );//原图反着走一遍
        s.x = r - 1;s.y = ty;s.c = 0;
        t.x = -1;t.y = sy;//越界的。。
        dfs (s);//反着走
        if (all() ) puts ("YES");
        else puts ("NO");
    }
    return 0;
}
/*
100
2 2 0 1
0
1 0
0

*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,HDU1622是一道关于二叉树的题目,要求读入一系列二叉树的节点信息,输出它们的层序遍历结果。如果输入的二叉树不完整或存在重复节点,则输出"not complete"。下面是Java的实现代码: ```java import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; public class Main { static class Node { int val; Node left, right; public Node(int val) { this.val = val; } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { String s = sc.nextLine(); if (s.isEmpty()) { continue; } String[] nodes = s.split("\\s+"); Node root = new Node(Integer.parseInt(nodes[0].substring(1))); Queue<Node> queue = new LinkedList<>(); queue.offer(root); boolean isComplete = true; for (int i = 1; i < nodes.length - 1; i += 2) { Node cur = queue.poll(); if (!nodes[i].equals("()")) { cur.left = new Node(Integer.parseInt(nodes[i].substring(1))); queue.offer(cur.left); } else { isComplete = false; } if (!nodes[i + 1].equals("()")) { cur.right = new Node(Integer.parseInt(nodes[i + 1].substring(0, nodes[i + 1].length() - 1))); queue.offer(cur.right); } else { isComplete = false; } } if (!isComplete) { System.out.println("not complete"); continue; } StringBuilder sb = new StringBuilder(); queue.offer(root); while (!queue.isEmpty()) { Node cur = queue.poll(); sb.append(cur.val).append(" "); if (cur.left != null) { queue.offer(cur.left); } if (cur.right != null) { queue.offer(cur.right); } } System.out.println(sb.toString().trim()); } } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值