题解-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个点分成数量相等的两部分 并在这条直线上取不同的两个点,表示 ...
随机推荐
- prop()和attr()我该翻谁的牌子?
先上代码: // 全选 function CheckAll() { if ($("#th_checkbox").prop('checked')) $('input[name=&qu ...
- JsonPath在接口自动化中的应用
我理解jsonpath于json而言,就像是xpath在XML中的作用.用来确定json中某部分数据的语言.我更喜欢叫jsonpath表达式,因为这样好像是数学问题. 以前和小伙伴一起写接口自动化的时 ...
- Linux程序开发中如何判断目录是否为根目录?
问题引入 判断某个目录字符串是否是根目录,咋一听很简单,只要判断字符串是否是"/"即可,但是,很多情况下使用的路径是相对路径,那么如何判断相对路径是根目录呢? 思路分析 熟悉Lin ...
- 删除ceph集群mds
ceph集群新搭建以后是只有一个默认的存储池rbd的池 ## 创建文件接口集群 1.创建一个元数据池 [root@mytest ~]# ceph osd pool create metadata 20 ...
- C#高级编程之反射
反射的定义 MSDN定义:反射提供描述程序集.模块和类型的对象(Type类型). 可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型,然后调用其方法或访问器字段和属性. 如 ...
- python any,call,init,下划线知识汇总
python补充 any() [来自菜鸟教程] any() 函数用于判断给定的可迭代参数 iterable 是否全部为 False,则返回 False,如果有一个为 True,则返回 True. 元素 ...
- springboot中aop的使用
Spring AOP(Aspect Oriented Programming),即面向切面编程,是OOP(Object Oriented Programming,面向对象编程)的补充和完善. OOP引 ...
- 直面秋招!非科班生背水一战,最终拿下阿里等大厂offer!
前言 2020年已经接近到9月份了,很多粉丝朋友都对金九银十雀雀欲试了吧!也有很多朋友向我求教经验,因为我自己工作相对于稳定,在这里给大家分享一个粉丝朋友的经历,他作为一个曾经的菜鸡面试者,在不断的失 ...
- 如何制作C语言基本数据类型的思维导图
在使用C语言编写程序时,数据类型是一个非常重要的内容,任何一个不被重视的数据错误都会使编译器无法翻译,导致程序报错. 使用思维导图来梳理各个数据类型是一个很有效的记忆方法,接下来就为大家展示一下我用i ...
- 怎么用iMindMap思维导图做自我介绍
相信大家在工作生活当中对于自我介绍这件事情都很是头疼的.太简单的介绍重点不突出,太冗长的介绍又会让人没印象.这一切都跟我们大脑水平.散乱的思维模式有关,因此想要自我介绍在众人中脱颖而出,让人印象深刻, ...