【CF1117】【二分】Magic Ship

Educational Codeforces Round 60 (Rated for Div. 2)

题目链接

【小结】:

掉分了,同时也说明自己还需要锻炼锻炼,过年期间就没有打过比赛,原因还是太懒了。回来一直跟不上训练量了,大伙都做出来的题目,我也要错几遍才甘心,还有几天就开学了,不能拖到上课时候补题了,原因:上课时候更忙,有些时间段不是自己说了算,还有上课不仅更忙了,人也就会更多借口。抓紧时间能补题就补题,能写模板多学几个算法防身。这个学期注定也是忙碌的一个学期。不仅乱七八糟的课程多,还有一些比赛需要自己准备,模板还没整理,算法现在很多都是停留在基础上(即只会套模板,而不懂灵活运用)。最近也把《王室战争》给卸载了,正如老高说我的一样,“屡卸屡玩,屡玩屡卸”。玩游戏也只是寒假真的太无聊了,你叫我看书学习,真的不可能的,所以只能玩玩游戏。回来几天了,发现自己补题速度太慢了,所以没有办法的事,不卸游戏可能我每天都在这里浪费好几个小时。

【题意】:

有一艘船,从 (X1,Y1)->(X2,Y2),但是有n天,每天都是打风,风向会向上下左右吹,然后船只每天都可以上下左右地开,也可以船不动等风吹。风向的速度和船只的速度一样。也就是说,对于逆风而行,可以停留原点。

和高中学船只过河,河流速度是一回事。还记得当时最短距离,最短时间。

一开始我以为可以贪心来做:后来发现不是那么一回事,可以看事例二:

(0,3)->(0,0)时,如果贪心来做,第一天U我是不走的。

那么就有很多情况需要枚举:顺风而行,垂直方向左,垂直方向右,船只不动。

而且枚举的时候,发现你不能通过找循环节来解决。因为当前位置贪心,而没有从整体来考虑。

后来发现这个不可行。


赛后看了一些Tag是二分,又看了一些别人大佬的代码:发现原来这个题目用的是二分,为什么想到是二分呢???其实我们可以从另外一个角度来分析,Dx=x2-x1,Dy=y2-y1.无论正负。

我们行驶的路程,虽然有x,y轴上面之分,但是不外乎由两部分来组成,第一部分就是风向,第二部分就是人为行驶。风向就是前缀和,而人为行驶就是天数。我们只要(Dx-x前缀和)+(Dy-y前缀和)小于等于天数即可。

为什么有这样的判断条件呢???

D肯定是有正有负,前缀和也是可能有正有负的,只要我们把他们两个差值能通过人为,天数进行弥补即说明能到达。

譬如,事例三,(0,0)->(1,0),风向一直是L。

那么前缀和就是-1.  D=1-(-1)=2.一天下来差距就是2,无论经过多少天差距只能拉近1.

注意:正负之分,也只是方向问题,Dx=x2-x1,如果Dx>0,说明在需要向右行驶。Dx<0,说明再需要向左行驶。而同时前缀和的正负也一样,两者作差,经过了i天后的差值为多少。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
const ll inf=0x3f3f3f3f3f3f3f3f;
int Sx,Ex,Sy,Ey,Dx,Dy,n;
int X[N],Y[N];
char s[N];
bool check(ll mid){
    ll K=mid/n;
    ll R=mid%n;
    ll tx=K*X[n];
    ll ty=K*Y[n];
    if(R){
        tx+=X[R];
        ty+=Y[R];
    }
    ll D=llabs(tx-Dx)+llabs(ty-Dy);
    return mid>=D;
}
int main()
{
    scanf("%d%d%d%d",&Sx,&Sy,&Ex,&Ey);
    scanf("%d%s",&n,s+1);
    Dx=Ex-Sx;
    Dy=Ey-Sy;
    for(int i=1;i<=n;i++){
        switch(s[i]){
            case 'U':Y[i]++;break;
            case 'D':Y[i]--;break;
            case 'L':X[i]--;break;
            case 'R':X[i]++;break;
        }
        X[i]=X[i]+X[i-1];
        Y[i]=Y[i]+Y[i-1];
    }
    ll L=1,R=inf,ans=inf;
    while(L<=R){
        ll mid=(L+R)>>1;
        if(check(mid)){
            ans=mid;
            R=mid-1;
        }else{
            L=mid+1;
        }
    }
    if(ans==inf) puts("-1");
    else    printf("%lld\n",ans);
}

猜你喜欢

转载自blog.csdn.net/Z_sea/article/details/87713966