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的更多相关文章

  1. 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 ...

  2. C. Magic Ship cf 二分

    C. Magic Ship time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...

  3. CF1117C Magic Ship

    CF1117C Magic Ship 考虑到答案具单调性(若第 \(i\) 天能到达目的点,第 \(i+1\) 天只需向风向相反的方向航行),可以二分答案. 现在要考虑给出一个天数 \(m\) ,问 ...

  4. 【Codeforces 1117C】Magic Ship

    [链接] 我是链接,点我呀:) [题意] 题意 [题解] 我们可以把这个行船的过程分解成两个过程 1.船经过时间t被风吹到了某个地方 2.船用这t时间尝试到达终点(x2,y2) 会发现如果时间t能最终 ...

  5. 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 ...

  6. CodeForces 1117C Magic Ship (循环节+二分答案)

    <题目链接> 题目大意: 给定起点和终点,某艘船想从起点走到终点,但是海面上会周期性的刮风,船在任何时候都能够向四个方向走,或者选择不走,船的真正行走路线是船的行走和风的走向叠加的,求船从 ...

  7. C. Magic Ship (思维+二分)

    https://codeforces.com/contest/1117/problem/C 你是一个船长.最初你在点 (x1,y1) (显然,大海上的所有点都可以用平面直角坐标描述),你想去点 (x2 ...

  8. 【Codeforces1117C_CF1117C】Magic Ship(构造)

    题目: Codeforces1117C 考的时候很困,开局半小时后才过A,只做出来AB,排名3000+,掉了119--半夜体验极差. 翻译: 你是一个船长.最初你在点 \((x_1,y_1)\) (显 ...

  9. [题解]Magic Line-计算几何(2019牛客多校第三场H题)

    题目链接:https://ac.nowcoder.com/acm/contest/883/H 题意: 给你偶数个点的坐标,找出一条直线将这n个点分成数量相等的两部分 并在这条直线上取不同的两个点,表示 ...

随机推荐

  1. centos7安装数据库 (系统包含预装环境mariadb)

    查看系统是否安装了MySQL,有些没安装但是有路径,那是因为系统安装了mariadb-libs,对应的配置文件目录:/etc/my.cnf(下面就根据mariadb来安装mysql) 查看系统预装ma ...

  2. LeetCode283移动零问题java高效解法

    一.题目: 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序. 示例: 输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明: 1.必须 ...

  3. JS处理Long类型精度丢失问题

    解决方式一 json注解 public class ProductVo {​   @JsonSerialize(using=ToStringSerializer.class)   private Lo ...

  4. 如何灵活运用ABBYY FineReader的识别功能

    由于工作的原因,经常会使用到文字识别工具,说真的,一款好用的文字识别工具能省不少事,前不久碰到一位职场新人,他的工作内容也离不开文字识别工具,他还问我有什么好用的软件推荐,说到好用,还是ABBYY F ...

  5. Camtasia中如何自定义视频输出格式

    Camtasia Studio是一款功能全面.操作简单的视频录制和编辑软件,它是很多需要进行录屏操作,比如制作教学视频的用户的不错选择.Camtasia 2020还为用户提供了极大的便利的全面的服务, ...

  6. 加密PDF文件,提高文件安全性

    PDF文件的一大优点是可以设置文件的安全性,不仅可以通过证书加密的形式加密文件,还可以通过pdfFactory来设置密码的形式加密文件. 我们可以通过两种方式开启"PDF加密"来为 ...

  7. Boom 3D支持的音乐都有什么格式

    Boom 3D作为一款专业的3D环绕音效软件,支持多种音频.视频播放格式,除了常用的MP3.WMA.WAV音频格式外,Boom 3D还支持FLAC.AAC这些比较高级的音频格式.同时,Boom 3D还 ...

  8. 【电子取证:镜像仿真篇】Windows Server镜像仿真、vmdk镜像仿真

    Windows Server镜像仿真.vmdk镜像仿真 时间过得真快呀!--[suy999] Windows Server镜像仿真.vmdk镜像仿真 一.qemu-img镜像转换工具 (一)raw.q ...

  9. iOS沙盒文件目录介绍

    1.APP沙盒目录结构简介 首先奉上苹果官方文档: https://developer.apple.com/library/archive/documentation/FileManagement/C ...

  10. C语言初级编程实践:2048小游戏

    大部分同学学习C语言编程以后不知道能通过什么样的项目才可以锻炼自己的思维功力,2048相信大家都应该熟悉,不管是手机上还是网页版的相信大家都玩过,这个简单的控制台版本的游戏是我曾经在伟易达上班时一个嵌 ...