标签:scan char s 选择 数据 std cond 二分 ble bit
你在 \((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;
}
标签:scan char s 选择 数据 std cond 二分 ble bit
原文地址:https://www.cnblogs.com/Wendigo/p/12819305.html