【Educational Codeforces Round 53 (Rated for Div. 2) C】Vasya and Robot

本文深入探讨了机器人从原点到达指定坐标(x,y)的路径规划算法,通过分析|x|+|y|与n的关系判断可达性,并采用二分搜索策略寻找最短操作序列长度,确保机器人能在限定步数内准确抵达目标。

【链接】 我是链接,点我呀:)
【题意】

【题解】


如果|x|+|y|>n
显然。从(0,0)根本就没法到(x,y)
但|x|+|y|<=n还不一定就能到达(x,y)
注意到,你每走一步路 |x|+|y|的奇偶性会发改变奇变偶,偶变奇。
因此,如果|x|+|y|的奇偶性和n不一样的话。
显然也是没法走到(x,y)的
可以这么理解,先走|x|+|y|步到达(x,y)
然后n-(|x|+|y|)显然是一个偶数(奇偶性一样的话,相减为偶数)
因此,它肯定又能走回来。
————————————————————————
这两种情况去除掉之后。就一定有解了。
怎么找到这个解?
题中要求的值,转化一下。
其实就是说有一段区间[l..r]
你可以将s[l..r]中的字符任意改变。
然后使得s[1..n]操作之后,能从原点走到(x,y)
请你求出r-l+1的最小值,也即区间长度的最小值。
会发现。
如果长度为x的区间可以满足要求的话。
那么长度为x+1的区间肯定也可以满足要求。
因此可以二分。
————————————————————
我们二分最后的长度len
然后枚举这个区间的起点i
设s[1..i-1]和s[i+len-1+1..n]这两段操作过后,能从(0,0)走到(x0,y0)
(先走前面和后面这两段不影响
那么我们接下来要考虑的问题就是,s[i..i+len-1]这一段操作序列能否让机器人从(x0,y0)走到(x,y)
设temp1 = abs(x0-x)+abs(y0-y)
如果temp1<=len
那么就一定有解。
因为我们可以再花费temp1步从(x0,y0)走到(x,y)
设temp2 = i-1 + n-i;
剩下rest=n-temp1-temp2步要走。
我们总能从这temp1+temp2中提出来|x|+|y|步是从(0,0)不绕弯路直接走到(x,y)的。
这个|x|+|y|<=temp1+temp2
而我们现在的位置又回到了(x,y)
这就说明temp1+temp2-(|x|+|y|)为偶数。
也即temp1+temp2的奇偶性和|x|+|y|相同。
那么根据题解一开始的分析|x|+|y|的奇偶性和n相同(不然无解);
因此temp1+temp2的奇偶性和n也相同。
那么rest的值就肯定为一个偶数了.(两个奇偶性相同的数字相减,肯定是一个偶数).
因此我们总能再次回到(x,y)这个位置的。也即满足要求。
那么返回true.

【代码】

#include <bits/stdc++.h>
#define ll long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
using namespace std;

const int N = 2e5;

int n;
ll x,y;
ll px[N+10],py[N+10];
char s[N+10];

bool ok(int len){
    rep1(i,1,n){
        if (i+len-1>n) return 0;
        ll x0 = px[i-1]-px[0],y0=py[i-1]-py[0];
        x0+=px[n]-px[i+len-1];y0+=py[n]-py[i+len-1];
        ll temp = abs(x-x0)+abs(y-y0);
        if (temp<=len) return 1;
    }
    return 0;
}

int main(){
    #ifdef ccy
            freopen("rush.txt","r",stdin);
    #endif
    scanf("%d",&n);
    scanf("%s",s+1);
    scanf("%lld%lld",&x,&y);
    ll temp = abs(x)+abs(y);
    if (temp>n || ( (temp&1) != (n&1) ) ){
        puts("-1");
        return 0;       
    }
    rep1(i,1,n){
        px[i] = px[i-1];py[i] = py[i-1];
        if (s[i]=='L') px[i]--;
        if (s[i]=='R') px[i]++;
        if (s[i]=='U') py[i]++;
        if (s[i]=='D') py[i]--;
    }
    int l = 0,r = n,temp1 = -1;
    while (l <= r){
        int mid = (l+r)>>1;
        if (ok(mid)){
            temp1 = mid;
            r = mid-1;
        }else{
            l = mid+1;
        }
    }
    printf("%d\n",temp1);
    return 0;
}

转载于:https://www.cnblogs.com/AWCXV/p/9925526.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值