C. Pipes(DFS或思维枚举解决) Codeforces Round #590 (Div. 3)

原题链接: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爆搜,另一种是直接枚举。

  1. 直接枚举
    我们可以直接按照给出的管子图来进行判断能不能达成目的,利用row表示行,利用line表示列。因为行号只有0和1,那么如果我们切换行号就可以直接!row,我们可以向右走也可以上下走,但要清楚的一点就是向右走行不变,列+1。向上下走列不变,行+1,且接下来必须向右走,若不行则是真不行。如果满足这些条件使得列号达到n,我们还要判断行号是否在第一行,若不在,也是不行的。这样枚举此题易解。
    AC代码:
/*
*邮箱:[email protected]
*blog:https://blog.csdn.net/hzf0701
*注:代码如有问题请私信我或在评论区留言,谢谢支持。
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<stack>
#include<queue>
#include<cstring>
#include<map>
#include<iterator>
#include<list>
#include<set>
#include<functional>
#include<memory.h>//低版本G++编译器不支持,若使用这种G++编译器此段应注释掉
#include<iomanip>
#include<vector>
#include<cstring>
#define scd(n) scanf("%d",&n)
#define scf(n) scanf("%f",&n)
#define scc(n) scanf("%c",&n)
#define scs(n) scanf("%s",n)
#define prd(n) printf("%d",n)
#define prf(n) printf("%f",n)
#define prc(n) printf("%c",n)
#define prs(n) printf("%s",n)
#define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
#define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
#define pb push_back
#define fi first
#define se second
#define mp make_pair
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;
}
  1. DFS搜索
    既然可以枚举,那么我们也同样可以进行搜索,直接让计算机去找路,返回判断结果即可,这里我们把它当成迷宫来处理,哪里可以走,哪里不可以走,走了之后状态时什么,由于不会出现重复路径,我们也不用标记,那么入口就是开头,出口我们要加一根水管来充当出口这样子来进行判断。这里还利用了由于水管真正只有两根,所以我们改符号即可让其变为两根,由于我们是对后续进行判断,所以我们要对开头进行处理,判断我们起始是在第几行,我们具体看代码。
    AC代码:
/*
*邮箱:[email protected]
*blog:https://blog.csdn.net/hzf0701
*注:代码如有问题请私信我或在评论区留言,谢谢支持。
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<stack>
#include<queue>
#include<cstring>
#include<map>
#include<iterator>
#include<list>
#include<set>
#include<functional>
#include<memory.h>//低版本G++编译器不支持,若使用这种G++编译器此段应注释掉
#include<iomanip>
#include<vector>
#include<cstring>
#define scd(n) scanf("%d",&n)
#define scf(n) scanf("%f",&n)
#define scc(n) scanf("%c",&n)
#define scs(n) scanf("%s",n)
#define prd(n) printf("%d",n)
#define prf(n) printf("%f",n)
#define prc(n) printf("%c",n)
#define prs(n) printf("%s",n)
#define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
#define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
#define pb push_back
#define fi first
#define se second
#define mp make_pair
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;
}

猜你喜欢

转载自blog.csdn.net/hzf0701/article/details/107815555