二分答案,作为一种极其基础的算法,想必大家都很了解,就是对于具有某种单调性的序列,每次取中值,判断其是否符合题意,从而逼近正确答案,通常用于解决最大的最小值或最小的最大值的问题,时间复杂度为O(logn)。其难题的难点往往在于寻找其单调性以及判断正确性。

  接下来是一道不久前我cf比赛见过的一道题目,颇有意思。

C. Magic Ship
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

You a captain of a ship. Initially you are standing in a point (x1,y1)(x1,y1) (obviously, all positions in the sea can be described by cartesian plane) and you want to travel to a point (x2,y2)(x2,y2).

You know the weather forecast — the string ss of length nn, consisting only of letters U, D, L and R. The letter corresponds to a direction of wind. Moreover, the forecast is periodic, e.g. the first day wind blows to the side s1s1, the second day — s2s2, the nn-th day — snsn and (n+1)(n+1)-th day — s1s1 again and so on.

Ship coordinates change the following way:

  • if wind blows the direction U, then the ship moves from (x,y)(x,y) to (x,y+1)(x,y+1);
  • if wind blows the direction D, then the ship moves from (x,y)(x,y) to (x,y1)(x,y−1);
  • if wind blows the direction L, then the ship moves from (x,y)(x,y) to (x1,y)(x−1,y);
  • if wind blows the direction R, then the ship moves from (x,y)(x,y) to (x+1,y)(x+1,y).

The ship can also either go one of the four directions or stay in place each day. If it goes then it's exactly 1 unit of distance. Transpositions of the ship and the wind add up. If the ship stays in place, then only the direction of wind counts. For example, if wind blows the direction U and the ship moves the direction L, then from point (x,y)(x,y) it will move to the point (x1,y+1)(x−1,y+1), and if it goes the direction U, then it will move to the point (x,y+2)(x,y+2).

You task is to determine the minimal number of days required for the ship to reach the point (x2,y2)(x2,y2).

Input

The first line contains two integers x1,y1x1,y1 (0x1,y110^0≤x1,y1≤10^9) — the initial coordinates of the ship.

The second line contains two integers x2,y2x2,y2 (0x2,y210^0≤x2,y2≤10^9) — the coordinates of the destination point.

It is guaranteed that the initial coordinates and destination point coordinates are different.

The third line contains a single integer nn (1n1051≤n≤105) — the length of the string ss.

The fourth line contains the string ss itself, consisting only of letters U, D, L and R.

Output

The only line should contain the minimal number of days required for the ship to reach the point (x2,y2)(x2,y2).

If it's impossible then print "-1".

Examples
input
0 0
4 6
3
UUU
output
5
input
0 3
0 0
3
UDD
output
3
input
0 0
0 1
1
L
output
-1
Note

In the first example the ship should perform the following sequence of moves: "RRRRU". Then its coordinates will change accordingly: (0,0)(0,0) → (1,1)(1,1) → (2,2)(2,2) → (3,3)(3,3) → (4,4)(4,4) → (4,6)(4,6).

In the second example the ship should perform the following sequence of moves: "DD" (the third day it should stay in place). Then its coordinates will change accordingly: (0,3)(0,3) → (0,3)(0,3) → (0,1)(0,1) → (0,0)(0,0).

In the third example the ship can never reach the point (0,1)(0,1).

  题目大意就是有条船,想要从给定的起点走到给定的终点,船可以自己移动也会被风吹动,风吹的方向有一个字符串给定,风的吹动以此为周期无限循环,风的吹动会使船移动一格,船自身也可移动一格。问船移动到终点最少需要移动几次,若无法达到则输出-1.

  当时我的第一反应是广度优先搜索,但是看到坐标的范围达到1e9之后就意识到bfs会超时,于是对题意进行观察,发现当船到达终点之后,无论风怎么吹,船都可以逆向开,使船保持原地不动,于是我们得到一个不明显的递增关系,若船可以到达终点,一定存在一个临界值,使得大于等于临界值的次数一定可以到终点,否则一定不能到达终点。这明显就可以用二分答案解决。不过由于风一直在吹,故而需要前缀和预处理一下,除去不必要的运算,避免超时。还有一点,就是二分的右边界应该设得足够大,我当初比赛时由于右边界只开到1e9而导致wa了两发。

  代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=(1e5)+5;
ll x1,y4,x2,y2,n;
string s;
ll cntx[maxn],cnty[maxn];
bool check(ll t){
    ll x3,y3;
    x3=x1+cntx[t%n]+(t/n)*cntx[n];
    y3=y4+cnty[t%n]+(t/n)*cnty[n];
    if(abs(x2-x3)+abs(y2-y3)<=t) return 1;
    return 0;
}
int main(){
    scanf("%lld%lld%lld%lld%lld",&x1,&y4,&x2,&y2,&n);
    cin>>s;
    ll l=0,r=(1e17)+5;
    ll ans=-1;
    for(int i=1;i<=n;i++){
        cnty[i]=cnty[i-1];
        cntx[i]=cntx[i-1];
        if(s[i-1]=='U')cnty[i]=cnty[i-1]+1;
        if(s[i-1]=='D')cnty[i]=cnty[i-1]-1;
        if(s[i-1]=='R')cntx[i]=cntx[i-1]+1;
        if(s[i-1]=='L')cntx[i]=cntx[i-1]-1;
    }
    while(l<=r){
        ll mid=(l+r)>>1;
        if(check(mid)){
            r=mid-1;
            ans=mid;
        }
        else{
            l=mid+1;
        }
    }
    printf("%lld",ans);
    return 0;
}

 

posted on 2021-08-13 11:31  雪之下雪乃天下第一  阅读(119)  评论(0)    收藏  举报