Codeforces-1234C Pips DFS深搜题解

● 本题解会有详细的分析,适合初学者阅读

原题

Problem Description

You are given a system of pipes. It consists of two rows, each row consists of nn pipes. The top left pipe has the coordinates (1,1)and the bottom right — (2,n).

There are six types of pipes: two types of straight pipes and four types of curved pipes. Here are the examples of all six types:

在这里插入图片描述

​ Types of pipes

You can turn each of the given pipes 9090 degrees clockwise or counterclockwise arbitrary (possibly, zero) number of times (so the types 1 and 2 can become each other and types 3,4,5,6 can become each other).

You want to turn some pipes in a way that the water flow can start at (1,0) (to the left of the top left pipe), move to the pipe at (1,1), flow somehow by connected pipes to the pipe at (2,n)(2,n) and flow right to (2,n+1).

Pipes are connected if they are adjacent in the system and their ends are connected. Here are examples of connected pipes:

​ Examples of connected pipes

Let’s describe the problem using some example:

在这里插入图片描述

​ The first example input

And its solution is below:

在这里插入图片描述

​ The first example answer

As you can see, the water flow is the poorly drawn blue line. To obtain the answer, we need to turn the pipe at (1,2)(1,2) 9090 degrees clockwise, the pipe at (2,3)(2,3) 9090 degrees, the pipe at (1,6)(1,6) 9090 degrees, the pipe at (1,7)(1,7) 180180 degrees and the pipe at (2,7)(2,7) 180180 degrees. Then the flow of water can reach (2,n+1)(2,n+1) from (1,0)(1,0).

You have to answer qq independent queries.

Input

The first line of the input contains one integer q ( 1 ≤ q ≤ 1 0 4 ) q (1≤q≤10^4) q(1q104) — the number of queries. Then q queries follow.

Each query consists of exactly three lines. The first line of the query contains one integer n ( 1 ≤ n ≤ 2 ⋅ 1 0 5 ) n (1≤n≤2⋅10^5) n(1n2105) — the number of pipes in each row. The next two lines contain a description of the first and the second rows correspondingly. Each row description consists of n digits from 1 to 6 without any whitespaces between them, each digit corresponds to the type of pipe in the corresponding cell. See the problem statement to understand which digits correspond to which types of pipes.

It is guaranteed that the sum of n over all queries does not exceed 2 ⋅ 1 0 5 2⋅10^5 2105.

Output

For the i − t h i-th ith query print the answer for it — “YES” (without quotes) if it is possible to turn some pipes in a way that the water flow can reach ( 2 , n + 1 ) (2,n+1) (2,n+1) from ( 1 , 0 ) (1,0) (1,0), and “NO” otherwise.

Example

Input

6
7
2323216
1615124
1
3
4
2
13
24
2
12
34
3
536
345
2
46
54

Output

YES
YES
YES
NO
YES
NO

题目翻译

Problem Description

你有一套管道系统。它由两行组成,每行由nn管道组成。左上方的管道具有坐标(1,1)和右下方的-(2,n)。
有六种类型的管道:两种类型的直管和四种类型的弯管。以下是所有六种类型的示例:图片自行翻阅上方原题,不再单独展示~

你可以将每个给定的管道顺时针或逆时针旋转90度任意(可能为零)次(因此类型1和2可以相互转换,类型3、4、5、6可以相互转换)。

你希望以水流可以从(1,0)处开始的方式转动某些管道(在左上方管道的左侧),移动(1,1)处的管道,通过连接管道流向(2,n)(2,n)处的管道,然后向右流向(2,n+1)。

如果管道在系统中相邻且其端部已连接,则将连接管道。以下是连接管道的示例:图片略

示例看图应该就看懂了,也不再翻译

Input

输入的第一行包含一个整数 q ( 1 ≤ q ≤ 1 0 4 ) q(1≤q≤10^4) q1q104—查询数。接着是q个询问。
每个询问由三行组成。查询的第一行包含一个整数 n ( 1 ≤ n ≤ 2 ⋅ 1 0 5 ) n(1≤n≤2⋅10^5) n1n2105代表—每行中的管道数。
接下来的两行分别包含第一行和第二行的描述。每行描述由1到6之间的n个数字组成,它们之间没有任何空格,每个数字对应于相应单元格中的管道类型。请参阅问题说明,以了解哪些数字对应于哪些类型的管道。
保证所有询问的n之和不超过 2 ⋅ 1 0 5 2⋅10^5 2105

Output

对于 i − t h i-th ith查询,如果通过一定的旋转可以使水流从 ( 1 , 0 ) (1,0) 1,0到达 ( 2 , n + 1 ) (2,n+1) 2n+1,则输出-“YES”(不带引号),否则输出“NO”。

题目分析

在这里插入图片描述

首先分析联通性:

当前格子 g [ i ] [ j ] g[i][j] g[i][j]的值 格子左方 g [ i ] [ j − 1 ] g[i][j - 1] g[i][j1] 格子右方 g [ i ] [ j + 1 ] g[i][j + 1] g[i][j+1] 格子上方 g [ i − 1 ] [ j ] g[i - 1][j] g[i1][j] 格子下方 g [ i + 1 ] [ j ] g[i + 1][j] g[i+1][j]
1 × × 1,3,4 1,5,6
2 2,3,6 2,4,5 × ×
3 × 2,4,5 × 1,5,6
4 2,3,6 × × 1,5,6
5 2,3,6 × 1,3,4 ×
6 × 2,4,5 1,3,4 ×

不难发现:

向左连接
无法连接
2, 3, 6
向右连接
无法连接
2, 4, 5
向上连接
无法连接
1, 3, 4
向下连接
无法连接
1, 5, 6

而通过旋转:类型1,2/类型3、4、5、6可以相互转换!因此将1,2当成1个管道,3,4,5,6当成一个管道来看待。
那么管道只剩平、拐两种类型!

再回读题目:这道题的图是比较简单的,仅有两行构成,恰好由上下两个边界构成两行,且起点固定: 从 ( 1 , 0 ) (1, 0) (1,0)出发,那么我们可以对状态进行进一步锁定:首先看一下图片分析(拐类型的管道自行脑部吧…不想画了,大致就那么个意思)

在这里插入图片描述

对于在第一行的情况下,我们可以发现:向上走不合法,向左走属于原路返回行为,对答案产生的是负贡献,因此对于第一行,如果相邻的管道合法,那么只能向右、下两个方向搜索

在这里插入图片描述

对于在第二行的情况下,我们可以发现:向下走不合法,向左走要么属于原路返回,产生负贡献;要么再次回到第一行进行死循环(其实也是负贡献),因此相邻合法的前提下,只能向右、上两个方向搜索。

再结合一开始的分析:向下/向上时只能选拐类型的管道,向右可平可拐

结合最开始的联通性分析,我们可以得出以下联通性表述示意图:

DFS-x,y,方向
y>= n, 搜索越界
return
x== 1且y==n-1且方向向右
搜索成功
x == 0, 位于第一行
方向向下,那么选择拐类型的管道向右搜
方向向右,分类讨论,选平的向右搜,选拐的向下搜
x==1,位于第二行
方向向上,那么选择拐类型的管道向右搜
方向向右,分类讨论,选平的向右搜,选拐的向上搜

实际上,这就是DFS的框架。根据框架写出对应的程序,即为本题目的解。

AC Code

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
bool flag = 0;
char g[2][2 * N];
int n = 0;


//!dfs方向:tar = l向左,r向右,u向上,d向下
void dfs(int x, int y, char tar){
    
    
    if(y >= n) return;
    if(x == 1 && y == n - 1 && tar == 'r'){
    
    
        flag = true;
        return;
    }
    if (x == 0){
    
    
        if(tar == 'd' && g[x + 1][y] != '1' && g[x + 1][y] != '2')dfs(x + 1, y, 'r');
        else if(tar == 'r'){
    
    
            if(g[x][y + 1] == '1' || g[x][y + 1] == '2') dfs(x, y + 1, 'r');
            else dfs(x, y + 1, 'd');
        }
    }
    else{
    
    
        if(tar == 'u' && g[x - 1][y] != '1' && g[x - 1][y] != '2') dfs(x - 1, y, 'r');
        else if(tar == 'r'){
    
    
            if(g[x][y + 1] == '1' || g[x][y + 1] == '2') dfs(x, y + 1, 'r');
            else dfs(x, y + 1, 'u');
        }
    }
}
int main(){
    
    
    int t; cin >> t;
    while (t--){
    
    
        cin >> n >> g[0] >> g[1];
        flag = false;
        if(g[0][0] == '1' || g[0][0] == '2') dfs(0, 0, 'r');
        else dfs(0, 0, 'd');
        if(flag) cout << "YES" << endl;
        else cout << "NO" << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yanweiqi1754989931/article/details/113063558