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