Contest1786 - 2019年第二阶段我要变强个人训练赛第十场 问题 A: Kenken Race dp超车

39 篇文章 0 订阅

题目链接:http://icpc.upc.edu.cn/problem.php?cid=1786&pid=0

题目描述

There are N squares arranged in a row, numbered 1,2,...,N from left to right. You are given a string S of length N consisting of . and #. If the i-th character of S is #, Square i contains a rock; if the i-th character of S is ., Square i is empty.
In the beginning, Snuke stands on Square A, and Fnuke stands on Square B.
You can repeat the following operation any number of times:
Choose Snuke or Fnuke, and make him jump one or two squares to the right. The destination must be one of the squares, and it must not contain a rock or the other person.
You want to repeat this operation so that Snuke will stand on Square C and Fnuke will stand on Square D.
Determine whether this is possible.

Constraints
4≤N≤200000
S is a string of length N consisting of . and #.
1≤A,B,C,D≤N
Square A, B, C and D do not contain a rock.
A, B, C and D are all different.
A<B
A<C
B<D

 

输入

Input is given from Standard Input in the following format:

N A B C D
S

 

 

输出

Print Yes if the objective is achievable, and No if it is not.

 

样例输入

复制样例数据

7 1 3 6 7
.#..#..

样例输出

Yes

题解: 若c==d肯定不行,若c<d,那肯定b先到d,然后a再到c,判断是否可以成立,若c>d,先看看像第二种方法能不能跑过去,如果不能的话,那就看看,中途a能不能超车,超车的条件是有至少连续三个空地。

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 200100;

char s[N];
int dp[N];
int n;
int a, b, c, d;
int main() {

	while(~scanf("%d %d %d %d %d", &n, &a, &b, &c, &d)) {
		scanf("%s", s + 1);
		if( c == d ) {
			printf("No\n");
			continue;
		}
		for(int i = 0; i <= n; i++) dp[i] = 0;
		if(c < d) {
			dp[b] = 1;
			for(int i = b + 1; i <= d; i++) {
				if(s[i] == '#' ) continue;
				dp[i] = dp[i - 1] | dp[i - 2];
			}
			if(!dp[d]) {
				printf("No\n");
				continue;
			}
			for(int i = 0; i <= n; i++) dp[i] = 0;
			dp[a] = 1;
			for(int i = a + 1; i <= c; i++) {
				if(s[i] == '#' || i == d) continue;
				dp[i] = dp[i - 1] | dp[i - 2];
			}
			if(!dp[c]) {
				printf("No\n");
				continue;
			}
			printf("Yes\n");
		} else {
			dp[b] = 1;
			for(int i = b + 1; i <= d; i++) {
				if(s[i] == '#' ) continue;
				dp[i] = dp[i - 1] | dp[i - 2];
			}
			if(!dp[d]) {
				printf("No\n");
				continue;
			}
			for(int i = 0; i <= n; i++) dp[i] = 0;
			dp[a] = 1;
			for(int i = a + 1; i <= c; i++) {
				if(s[i] == '#' || i == d) continue;
				dp[i] = dp[i - 1] | dp[i - 2];
			}
			if(dp[c]) {
				printf("Yes\n");
				continue;
			}
			for(int i = 0; i <= n; i++) dp[i] = 0;
			dp[a] = 1;
			for(int i = a + 1; i <= c; i++) {
				if(s[i] == '#' ) continue;
				dp[i] = dp[i - 1] | dp[i - 2];
			}
			int flag = 0;
			for(int i = b - 1; i <= d- 2; i++) {
				if(s[i] == '.' && s[i + 1] == '.' && s[i + 2] == '.')
					flag = 1; 
			}
			printf(dp[c] && flag ? "Yes\n" : "No\n");
		}
		
	}

	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值