题解-Magic Ship

Magic Ship

你在 \((x_1,y_1)\),要到点 \((x_2,y_2)\)。风向周期为 \(n\),一个字符串 \(s\{n\}\) 表示风向(每轮上下左右),每轮你都会被风向吹走一格。你可以在被风吹得被动移动的基础上选择每轮移动一格或不移动。求最少几轮可以到达终点。

数据范围:\(0\le x_1,y_1,x_2,y_2\le 10^9\)\(1\le n\le 10^5\)


一句话题解:分每个周期讨论,得出与终点的距离与轮数的函数图像单调递减的结论,二分答案。


令起点为 \((0,0)\),令终点为 \((ex=x_2-x_1,ey=y_2-y_2)\),消除起点位置的影响。

\(w('U')=(0,1),w('D')=(0,-1),w('L')=(-1,0),w('R')=(1,0),\vec{m_i}=w(s_i)\)

令位移前缀和 \(\vec{ad_i}=\sum_{j=1}^i \vec{m_i}\),所以周期总位移为 \(\vec{ad_n}\)


设当前走了 \(k\) 轮:

假如不考虑人主动的走动,只考虑风吹人动,那么人的位置为

未完待续


#include <bits/stdc++.h>
using namespace std;

//Start
#define lng long long
#define db double
#define mk make_pair
#define pb push_back
#define fi first
#define se second
#define rz resize
#define sz(x) (int)((x).size())
const int inf=0x3f3f3f3f;
const lng INF=0x3f3f3f3f3f3f3f3f;

//Data
const int N=1e5;
int n; char s[N+7];
lng ans=INF;

//Point
typedef pair<lng,lng> point;
point st,ed,ad[N+7];
lng dis(point x,point y){return abs(x.fi-y.fi)+abs(x.se-y.se);}
point operator-(const point x,const point y){return mk(x.fi-y.fi,x.se-y.se);}
point operator+(const point x,const point y){return mk(x.fi+y.fi,x.se+y.se);}
point operator*(const point x,const lng y){return mk(x.fi*y,x.se*y);}

//Main
int main(){
	scanf("%lld%lld%lld%lld%d%s",&st.fi,&st.se,&ed.fi,&ed.se,&n,&s[1]);
	ed=ed-st;
	if(ed.fi==0&&ed.se==0) return puts("0"),0;
	for(int i=1;i<=n;i++)
		if(s[i]=='U') ad[i]=ad[i-1]+mk(0,1);
		else if(s[i]=='D') ad[i]=ad[i-1]+mk(0,-1);
		else if(s[i]=='L') ad[i]=ad[i-1]+mk(-1,0);
		else if(s[i]=='R') ad[i]=ad[i-1]+mk(1,0);
	for(int i=1;i<=n;i++){
		lng l=-1,r=1e12+1;
		while(l<r-1){
			lng mid((l+r)>>1);
			if(dis(ad[i]+ad[n]*(mid),ed)-mid*n-i<=0) r=mid;
			else l=mid;
		}
		if(dis(ad[i]+ad[n]*r,ed)-r*n-i<=0) ans=min(ans,r*n+i);
	}
	if(ans==INF) puts("-1");
	else printf("%lld\n",ans);
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/Wendigo/p/12819305.html