原题链接:https://codeforces.com/contest/1234/problem/C


Input
 第一行输入一个整数 q (1 <= q <= 10000) — 表示样例个数.
每一个样例包含3行. 第一行输入整数 n (1 <= n <= 200000) — 代表网格长度为n. 接下来的两行输入两串数字表示各个空格的线段(1~6).
Output
 对于第 i 个样例 可以连接就输出 “YES” . 不可以就输出 “NO” .
Example
 Input
 5
 7
 1415115
 2514223
 2
 13
 24
 1
 3
 4
 3
 536
 356
 2
 12
 34
Output
 YES
 YES
 YES
 YES
 NO
题意:给定每个格子中的管子类型和格子的列数,判断这些水管能否按要求连接在一起。
解题思路:我们应该要知道虽然有六根管子,但由于管子是可以旋转的,所以实际上只有两根管子。那么事情自然就变得简单了,我们有两种思路来解决此问题,一种是DFS爆搜,另一种是直接枚举。
- 直接枚举
 我们可以直接按照给出的管子图来进行判断能不能达成目的,利用row表示行,利用line表示列。因为行号只有0和1,那么如果我们切换行号就可以直接!row,我们可以向右走也可以上下走,但要清楚的一点就是向右走行不变,列+1。向上下走列不变,行+1,且接下来必须向右走,若不行则是真不行。如果满足这些条件使得列号达到n,我们还要判断行号是否在第一行,若不在,也是不行的。这样枚举此题易解。
 AC代码:
/*
。
*/
//低版本G++编译器不支持,若使用这种G++编译器此段应注释掉
//i为循环变量,a为初始值,n为界限值,递增
//i为循环变量, a为初始值,n为界限值,递减。
using namespace std;
const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 2e5+2;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll>  pll;
typedef pair<int, int> pii;
//*******************************分割线,以上为代码自定义代码模板***************************************//
int main(){
    //freopen("D://123.txt", "r", stdin);//提交的时候要注释掉
    ios::sync_with_stdio(false);//打消iostream中输入输出缓存,节省时间。
    cin.tie(0); cout.tie(0);//可以通过tie(0)(0表示NULL)来解除cin与cout的绑定,进一步加快执行效率。
    int q;
    int n;
    char graph[2][maxn];
    while(cin>>q){
        while(q--){
            cin>>n;
            cin>>graph[0];
            cin>>graph[1];
            int row=0,line=0,dir=0;
            //low代表在第几行,line代表在第几列,dir代表方向问题。
            bool flag=false;//标志
            while(line<n){
                //我们知道走了一遍上下就一定要往右走的。我们做标志即可。
                if(dir==0){
                    //方向向右
                    if(graph[row][line]<='2'){
                        //往右走
                        line++;
                    }
                    else{
                        //往上下走。
                        dir=1;
                        row=!row;
                        //我们这里换行判断是不是。
                    }
                }
                else{
                    //方向为上下。
                    //可这一列不满足,我们则直接退出
                    if(graph[row][line]<='2'){
                        flag=true;
                        break;
                    }
                    else{
                        //满足上下走,增加列。
                        dir=0;
                        //改标志。
                        line++;
                    }
                }
            }
            if(flag||row==0){
                //若标志为真,或者行没到达第二层。
                cout<<"NO"<<endl;
            }
            else
                cout<<"YES"<<endl;
        }
    }
    return 0;
}- DFS搜索
 既然可以枚举,那么我们也同样可以进行搜索,直接让计算机去找路,返回判断结果即可,这里我们把它当成迷宫来处理,哪里可以走,哪里不可以走,走了之后状态时什么,由于不会出现重复路径,我们也不用标记,那么入口就是开头,出口我们要加一根水管来充当出口这样子来进行判断。这里还利用了由于水管真正只有两根,所以我们改符号即可让其变为两根,由于我们是对后续进行判断,所以我们要对开头进行处理,判断我们起始是在第几行,我们具体看代码。
 AC代码:
/*
*/
//低版本G++编译器不支持,若使用这种G++编译器此段应注释掉
//i为循环变量,a为初始值,n为界限值,递增
//i为循环变量, a为初始值,n为界限值,递减。
using namespace std;
const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 2e5+2;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll>  pll;
typedef pair<int, int> pii;
//*******************************分割线,以上为代码自定义代码模板***************************************//
char graph[2][maxn];
int q,n;
int dfs(int row,int line){
    //row代表行,line代表列。
    if(line==n){
        //还要判断是否在第一行。
        return row==1;
    }
    int ans=0;
    if(graph[row][line+1]=='1'){
        //此时能向右走,则行不变,列+1.
        ans+=dfs(row,line+1);
    }
    if(graph[row][line+1]=='2'&&graph[!row][line+1]=='2'){
        //此时上下走,行变化。列变化判断下一步
        ans+=dfs(!row,line+1);
    }
    return ans;
}
int main(){
    //freopen("in.txt", "r", stdin);//提交的时候要注释掉
    ios::sync_with_stdio(false);//打消iostream中输入输出缓存,节省时间。
    cin.tie(0); cout.tie(0);//可以通过tie(0)(0表示NULL)来解除cin与cout的绑定,进一步加快执行效率。
    while(cin>>q){
        while(q--){
            cin>>n;
            cin>>graph[0];
            cin>>graph[1];
            rep(j,0,n-1){
                if(graph[0][j]=='2')
                    graph[0][j]='1';
                else if(graph[0][j]>='2')
                    graph[0][j]='2';
                if(graph[1][j]=='2')
                    graph[1][j]='1';
                else if(graph[1][j]>='2')
                    graph[1][j]='2';
            }
            //由于初始位置我们要确定,因为从第几行开始我们是判断之后的行号。
            graph[1][n]='1';
            int ans=0;
            if(graph[0][0]=='1')
                ans+=dfs(0,0);
            if(graph[0][0]=='2'&&graph[1][0]=='2')
                ans+=dfs(1,0);
            if(ans)
                cout<<"YES"<<endl;
            else
                cout<<"NO"<<endl;
            }
    }
    return 0;
}                
                










