题解-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\)。
一句话题解:在最优行进策略中,人离终点的距离与风周期数之间的函数单调递减;二分答案轮数。
蒟蒻的前置准备:
先通过坐标系平移简化计算:将起点 \(start\) 置为原点,则终点 \(end\) 为 \((x_2-x_1, y_2-y_1)\)。
风向字符 \(s_i\) 对应的四个字符 \('U'\),\('D'\),\('L'\),\('R'\) 分别表示上下左右走一格,对应位移向量 \(\textrm{w}\) 为:
\(\textrm{w}('U')=(0,1)\),\(\textrm{w}('D')=(0,-1)\),\(\textrm{w}('L')=(-1,0)\),\(\textrm{w}('R')=(1,0)\),字符 \(s_i\) 对应的位移向量 \(\vec{m_i}=\textrm{w}(s_i)\)。
令位移前缀和为:\(\vec{ad_i}=\sum_{j=1}^i \vec{m_i}\),则一个风周期的总位移为 \(\vec{ad_n}\)。
上式表明:尽管在一个长度为 \(n\) 轮的风周期内,人被移动的轨迹是复杂的,但每个风周期对人的轨迹影响是恒定的。因此按风周期来看,人的移动与风周期之间的关系是线性的。
设当前走了 \(k\) 轮:
假如不考虑人主动的走动,只考虑风吹人动,那么人的位置为 \(\left(ad_{k\bmod n}+ad_{n}\cdot \lfloor\frac kn\rfloor\right)\):

这时再考虑人的主动走动,在 \(k\) 轮中人最多走 \(k\) 步。
令 \(\textrm{dis}(a,b)\) 表示 \(a\) 和 \(b\) 两点间的曼哈顿距离(\(x\) 轴距离与 \(y\) 轴距离之和)。
所以如果 \(\textrm{dis}(end,now)\le k\),那么 \(k\) 轮以内即可到达终点。
找到单调性:
对于式子 \(\left(ad_{k\bmod n}+ad_{n}\cdot \lfloor\frac kn\rfloor\right)\):
如果枚举 \(i=k\bmod n\),则点 \(now\) 的移动轨迹可以是一条直线。

这时单独考虑 \(\textrm{dis}(end,now)\):

可以发现 \(\lfloor\frac kn\rfloor\leftrightarrow\textrm{dis}(end,now)\) 的函数图像如下:(如果随风就能飘到终点,折线能与 \(\lfloor\frac kn\rfloor\) 轴相切)

因为最终要比较 \(\textrm{dis}(end,now)\) 和 \(k\),所以作函数 \(\lfloor\frac kn\rfloor\leftrightarrow\textrm{dis}(end,now)-k\):

这时有个问题:这折线是否单调递减?蒟蒻拿图说服你你肯定不信,但是可以这么想:
目的是距离终点更近,风力和人力相等,所以就算风再捣乱,如果人走得和风对着干,与终点的距离也不会变大。
所以这个折线是单调递减的。
可是其实还有一种情况——该折线有平行于 \(\lfloor\frac kn\rfloor\) 轴的一段且与 \(\lfloor\frac kn\rfloor\) 轴没有交点,便说明对于当前的 \(i=k\bmod n\) 无解。
上文提到:
如果 \(\textrm{dis}(end,now)\le k\),那么 \(k\) 轮以内即可到达终点。
所以可以先如上文枚举 \(i=k\bmod n\),然后二分 \(\lfloor\frac kn\rfloor\),得到 \(\lfloor\frac kn\rfloor\leftrightarrow\textrm{dis}(end,now)-k\) 图像上 \(\le 0\) 的临界点整数 \(\lfloor\frac kn\rfloor\),\(k\) 就是对于这个 \(i\) 的答案。总答案是对于每个 \(i\) 的答案的最小值,如果对于每个 \(i\) 都无解,输出 \(-1\)。
如上图,\(\lfloor\frac kn\rfloor=2\),可以通过 \(i\) 推算出 \(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;
}
祝大家学习愉快!
题解-Magic Ship的更多相关文章
- Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship
Problem Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship Time Limit: 2000 mSec P ...
- C. Magic Ship cf 二分
C. Magic Ship time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...
- CF1117C Magic Ship
CF1117C Magic Ship 考虑到答案具单调性(若第 \(i\) 天能到达目的点,第 \(i+1\) 天只需向风向相反的方向航行),可以二分答案. 现在要考虑给出一个天数 \(m\) ,问 ...
- 【Codeforces 1117C】Magic Ship
[链接] 我是链接,点我呀:) [题意] 题意 [题解] 我们可以把这个行船的过程分解成两个过程 1.船经过时间t被风吹到了某个地方 2.船用这t时间尝试到达终点(x2,y2) 会发现如果时间t能最终 ...
- Educational Codeforces Round 60 (Rated for Div. 2) 即Codeforces Round 1117 C题 Magic Ship
time limit per test 2 second memory limit per test 256 megabytes input standard inputoutput standard ...
- CodeForces 1117C Magic Ship (循环节+二分答案)
<题目链接> 题目大意: 给定起点和终点,某艘船想从起点走到终点,但是海面上会周期性的刮风,船在任何时候都能够向四个方向走,或者选择不走,船的真正行走路线是船的行走和风的走向叠加的,求船从 ...
- C. Magic Ship (思维+二分)
https://codeforces.com/contest/1117/problem/C 你是一个船长.最初你在点 (x1,y1) (显然,大海上的所有点都可以用平面直角坐标描述),你想去点 (x2 ...
- 【Codeforces1117C_CF1117C】Magic Ship(构造)
题目: Codeforces1117C 考的时候很困,开局半小时后才过A,只做出来AB,排名3000+,掉了119--半夜体验极差. 翻译: 你是一个船长.最初你在点 \((x_1,y_1)\) (显 ...
- [题解]Magic Line-计算几何(2019牛客多校第三场H题)
题目链接:https://ac.nowcoder.com/acm/contest/883/H 题意: 给你偶数个点的坐标,找出一条直线将这n个点分成数量相等的两部分 并在这条直线上取不同的两个点,表示 ...
随机推荐
- Spring源码之循环依赖
https://www.cnblogs.com/longy2012/articles/12834762.html https://www.bilibili.com/video/BV1iD4y1o7pM ...
- 【翻译】指示器(indicator)的分类
参考 David Bianco在2015年发布的博文: http://detect-respond.blogspot.com/2013/07/on-misuse-of-indicators.html ...
- 如何使用会声会影制作动态logo字幕
日常生活中大家在参加一些婚礼.聚会的时候,LED屏幕上播放的视频里面常常会有一行字,它随着视频的播放自己也在不断地改变颜色,非常醒目.想必大家也想把这种动态文字用在自己的视频中,为视频增添亮点.那么今 ...
- 攻克弹唱第八课(吉他演奏的律动与funk音乐)
在本期文章中,笔者将为通过Guitar Pro 7吉他打谱软件与大家分享一下吉他律动与funk音乐的经验. 想必正在看这篇文章的进阶者和高手,都会考虑这样一个问题.我辛辛苦苦练习的大段solo和指弹曲 ...
- 如何用FL Studio将乐器组合与分层
有过音乐制作经历的小伙伴应该知道,我们在用以FL Studio20为代表的音乐编曲软件制作音乐时,往往需要在同一节奏点添加多种音效,这样可以使音乐听起来更具层次感.正因如此,我们就需要不断添加音符,就 ...
- mongodb查询前10条
mongo可以通过时间或者通过id来判断上一条记录或者下一条记录,我是通过id 前10条 db.数据库名称.find({ '_id': { '$lt': ids } }).sort({_id: -1} ...
- pytest失败重跑
一.说明 平常在做功能测试的时候,经常会遇到某个模块不稳定,偶然会出现一些bug,对于这种问题我们会针对此用例反复执行多次,最终复现出问题来.自动化运行用例时候,也会出现偶然的bug,可以针对单个用例 ...
- Luogu P4306 JSOI2010 连通数
tarjan有向图缩点的基础应用.把原图中某点的连通数转化为反向图中"能够到达某点的个数".缩点后,每个新点的贡献等于 原dcc大小 * f[i] 其中f[i]表示(包括该点自身) ...
- Java基础教程——Jshell
Jshell 从java9开始,java提供Jshell工具,可以输入代码片段并马上看到运行结果. 对于简单的Java语句测试,不需要新建文件,编译,运行了 Microsoft Windows [版本 ...
- Java基础教程——反射机制
Java反射机制 Java反射机制是Java语言的一个重要特性,使得Java语言具备"动态性": 在运行时获取任意一个对象所属的类的相关信息; 在运行时构造任意一个类的对象: 在运 ...