C. Hamiltonian Wall edu139 div2

Problem - C - Codeforces

题意是给你一个2*n的网格,让你一笔把所有的B涂满,并且只能涂一次,问你是否可行

分析:

其实分析的时候我想到了转移。每一次的结果是由上一次转移而来,所以如果前后矛盾的话,即不成立,可以分析出来有三种情况:

第一种:某一列全是B,那不管前一列怎么转移过来,上面的必然要走到下面,下面的必然要走一下上面,所以再往前推一格。两种情况,如果从上面走到下面,那上面是由i-1转移过来,同理下面

第二种:某一列有一个B,那就是由同一行的前一列所转移过来

第三种是第二种的另外一个情况,某一列的另外一个B

其实赛时的时候,这个我都看出来了,(也不难想)

但是不知道怎么去实现

可以用动态规划呀(动态规划记录路径)

从刚开始的开头赋值为1,进行转移。每一层的状态由它理论转移位置去进行转移,最后看看最后一列的B的位置上是否把开头的1转移过来。

其实这题可以很好的理解动态规划的状态转移的思想

f[i][1/2]为第i列的第一行和第i列的第二行的转移状态。

最后看看f[maxn][1] 或者f[maxn][2]是否有1

下面看代码:

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define IOS ios::sync_with_stdio(false), cin.tie(0);
#include<iostream>
#include<map>
#include<set> 
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
#include<algorithm>
#include<cmath>
#include<queue>
#include<deque>
using namespace std;
#define int long long
typedef long long ll;
typedef pair<int,int> PAII;
const int N=2e6+10,M=5050,INF=1e18,mod=998244353;
char ch[5][N];
int f[N][5],a[5][N];
signed main(){
    //IOS;
    int T;
    //T=1;
    cin>>T;
    while(T--)
    {
		int n;
		cin>>n;
		for(int i=1;i<=2;i++)
			for(int j=1;j<=n;j++)
			{
				cin>>ch[i][j];
				if(ch[i][j]=='B') a[i][j]=1;
				else a[i][j]=0;
			}
		int minn=n+1,maxn=-1,ff=0;
		for(int i=1;i<=n;i++)
		{
			f[i][1]=0;
			f[i][2]=0; 
			if(a[1][i]||a[2][i])
			{
				ff=1;
				minn=min(minn,i);
				maxn=max(maxn,i);
			}
		} 
		if(ff==0)
		{
			cout<<"YES\n";
			continue;
		}
		f[minn][1]=(a[1][minn]==1);
		f[minn][2]=(a[2][minn]==1);
		for(int i=minn+1;i<=maxn;i++)
		{
			if(a[1][i]==1&&a[2][i]==1)
			{
				f[i][1]=f[i-1][2];
				f[i][2]=f[i-1][1];
			}
			if(a[1][i]==1&&a[2][i]==0) f[i][1]=f[i-1][1];
			if(a[1][i]==0&&a[2][i]==1) f[i][2]=f[i-1][2];
		}
		if(f[maxn][1]||f[maxn][2]) cout<<"YES\n";
		else cout<<"NO\n";
	}
    return 0;
} 
/*
令f[i][1/2]为第i列的上面和下面分别可不可以走到 


*/ 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值