[Codeforces 1201D]Treasure Hunting(DP)

题面

有一个n*m的方格,方格上有k个宝藏,一个人从(1,1)出发,可以向左或者向右走,但不能向下走。给出q个列,在这些列上可以向上走,其他列不能向上走。可以重复经过同一个点。求从(1,1)出发,经过所有宝藏的最短路径长度

\(n,m,k,q \leq 2 \times 10^5\)

分析

贪心考虑,我们应该按照行一层一层的走。每一行应该从最左的宝藏走到最右的宝藏,或者从最右的宝藏走到最左的宝藏,然后找最近的一个可以向上走的列,走到另一行。

设\(dp[i][0/1]\)表示当前在第i行最左边的宝藏,或者最右边的宝藏,已经走完该行所有宝藏的最短距离

那么只要记录上一个有宝藏的行pre,分类讨论一下四种转移

\(dp[i][0]\)需要先走到第i行的最右端,再从第i行的最右端走到最左端

\(dp[i][1]\)需要先走到第i行的最右端,再从第i行的最右端走到最左端

另一个问题是如何计算(x1,y1)到(x2,y2)的距离。我们预处理在第i列左边最近的可以向上走的列lb[i],和最右边最近的列rb[i],那么我们走的列一定是lb[y1],lb[y2],rb[y1],rb[y2]四列中的一列。

如下图,假设y1<y2,走lb[y1]左侧的一列显然不如lb[y1]优,走rb[y2]右侧的一列显然不如rb[y2]优,而走rb[y1],lb[y2]中间的列和直接走rb[y1],lb[y2]一样

把经过这四列向上的距离统计出来就可以了

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define maxn 200000
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
int n,m,k,q;
vector<int>a[maxn+5];
int lb[maxn+5],rb[maxn+5];
int col[maxn+5];
ll dp[maxn+5][2];//走到最左侧/最右侧结束
ll calc(int y1,int y2,int line){//从y1到第line列,走上去,再到y2
return (ll)abs(y1-line)+abs(y2-line);
}
ll dist(int x1,int y1,int x2,int y2){
ll distx=abs(x1-x2);
ll disty=min(min(calc(y1,y2,lb[y1]),calc(y1,y2,lb[y2])),min(calc(y1,y2,rb[y1]),calc(y1,y2,rb[y2])));
return distx+disty;
}
int main(){
int x,y;
scanf("%d %d %d %d",&n,&m,&k,&q);
for(int i=1;i<=k;i++){
scanf("%d %d",&x,&y);
a[x].push_back(y);
}
for(int i=1;i<=q;i++){
scanf("%d",&col[i]);
}
sort(col+1,col+1+q);
col[0]=-INF;
col[q+1]=INF;
for(int i=1;i<=m;i++){
lb[i]=col[lower_bound(col+1,col+1+q,i)-col-1];
rb[i]=col[lower_bound(col+1,col+1+q,i)-col];
} sort(a[1].begin(),a[1].end());
if(!a[1].empty()){
dp[1][0]=dp[1][1]=a[1].back()-1;
a[1][0]=a[1].back();
//第一行必须从最后一个关键点往上走,否则就走不完所有关键点
}else{
a[1].push_back(1);
dp[1][0]=dp[1][1]=0;
}
int last=1;
for(int i=2;i<=n;i++){
if(!a[i].empty()){
sort(a[i].begin(),a[i].end());
ll l_to_l=dp[last][0]+dist(last,a[last].front(),i,a[i].front());//从pre行最左侧走到i行最左侧
ll r_to_l=dp[last][1]+dist(last,a[last].back(),i,a[i].front()); //从pre行最右侧走到i行最左侧
ll l_to_r=dp[last][0]+dist(last,a[last].front(),i,a[i].back());//从pre行最左侧走到i行最右侧
ll r_to_r=dp[last][1]+dist(last,a[last].back(),i,a[i].back());//从pre行最右侧走到i行最右侧
ll now=a[i].back()-a[i].front();//走完当前行的代价
dp[i][0]=min(l_to_r,r_to_r)+now;//先走到最右侧,最后到最左侧
dp[i][1]=min(l_to_l,r_to_l)+now;//先走到最左侧,最后到最右侧
last=i;
}
}
printf("%I64d\n",min(dp[last][0],dp[last][1])); }

[Codeforces 1201D]Treasure Hunting(DP)的更多相关文章

  1. Codeforces 1201D. Treasure Hunting

    传送门 看一眼感觉就是 $dp$,但是似乎状态太多了 考虑推推性质 首先每到一行都要把所有宝藏都走到,那么一定会走到最左边的和最右边的宝藏 注意到一旦走完所有宝藏时肯定是在最左边或者最右边的宝藏位置 ...

  2. 矩阵拿宝物--Codeforces 1201D - Treasure Hunting Codeforces Round #577 (Div. 2)

    网上题解比较少,自己比较弱研究了半天(已经过了),希望对找题解的人有帮助 题目链接:https://codeforc.es/contest/1201/problem/D 题意: 给你一个矩形,起始点在 ...

  3. Codeforces Round #577 (Div. 2) D. Treasure Hunting

    Codeforces Round #577 (Div. 2)  D. Treasure Hunting 这个一场div2 前面三题特别简单,这个D题的dp还是比较难的,不过题目告诉你了只能往上走,所以 ...

  4. [Codeforces 1214D]Treasure Island(dfs)

    [Codeforces 1214D]Treasure Island(dfs) 题面 给出一个n*m的字符矩阵,'.'表示能通过,'#'表示不能通过.每步可以往下或往右走.问至少把多少个'.'变成'#' ...

  5. codeforces 505C C. Mr. Kitayuta, the Treasure Hunter(dp)

    题目链接: C. Mr. Kitayuta, the Treasure Hunter time limit per test 1 second memory limit per test 256 me ...

  6. Codeforces Round #286 Div.1 A Mr. Kitayuta, the Treasure Hunter --DP

    题意:0~30000有30001个地方,每个地方有一个或多个金币,第一步走到了d,步长为d,以后走的步长可以是上次步长+1,-1或不变,走到某个地方可以收集那个地方的财富,现在问走出去(>300 ...

  7. codeforces 505C Mr. Kitayuta, the Treasure Hunter(dp)

    题意:有30001个岛,在一条线上,从左到右编号一次为0到30000.某些岛屿上有些宝石.初始的时候有个人在岛屿0,他将跳到岛屿d,他跳跃的距离为d.如果当前他跳跃的距离为L,他下一次跳跃的距离只能为 ...

  8. Codeforces.739E.Gosha is hunting(DP 带权二分)

    题目链接 \(Description\) 有\(n\)只精灵,两种精灵球(高级和低级),每种球能捕捉到第\(i\)只精灵的概率已知.求用\(A\)个低级球和\(B\)个高级球能捕捉到精灵数的最大期望. ...

  9. codeforces Hill Number 数位dp

    http://www.codeforces.com/gym/100827/attachments Hill Number Time Limits:  5000 MS   Memory Limits: ...

随机推荐

  1. Azure IoT 技术研究系列3

    上篇博文中我们将模拟设备注册到Azure IoT Hub中:我们得到了设备的唯一标识. Azure IoT 技术研究系列2-设备注册到Azure IoT Hub 本文中我们继续深入研究,设备到云.云到 ...

  2. 细数不懂Spring底层原理带来的伤与痛

    原文链接:https://www.jianshu.com/p/c9de414221ac?utm_campaign=haruki&utm_content=note&utm_medium= ...

  3. CSS3——制作人物走路的小动画

    一个很简单的小动画,但是还挺有意思的,就是找这种图片很麻烦,我这里把我找的一张图片贴上来,这张图片是我在网上找的,又改了背景色和大小. <!DOCTYPE html> <html l ...

  4. mybaits 时间查询DATE_FORMAT

    <if test="accountdayInout.inoutDateStart!=null"> and DATE_FORMAT(t.inout_date,'%Y-%m ...

  5. 靠!老师居然叫我们去写博弈论!!!结果写了一个晚上的博弈论,简直要死QAQ。。。发发博客休息一下。。。TAT。。。

    萌萌的糖果博弈 题目描述: 用糖果来引诱小朋友学习是最常用的手法,绵羊爸爸就是用糖果来引诱萌萌学习博弈的.他把糖果分成了两堆,一堆有A粒,另一堆有B粒.他让萌萌和他一起按照下面的规则取糖果:每次可以任 ...

  6. HDU 2037(贪心)

    “今年暑假不AC?” “是的.” “那你干什么呢?” “看世界杯呀,笨蛋!” “@#$%^&*%...” 确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会抛开电脑,奔向电视了.  ...

  7. IDEA集成Mybatis打印日志插件

    MyBatis Log Plugin :把 mybatis 输出的sql日志还原成完整的sql语句. 如下图所示,点击Tools>MyBatis Log Plugin 然后运行程序后,就会看到对 ...

  8. [ethereum源码分析](3) ethereum初始化指令

    前言 在上一章介绍了关于区块链的一些基础知识,这一章会分析指令 geth --datadir dev/data/02 init private-geth/genesis.json 的源码,若你的eth ...

  9. 前端开发学习笔记 - 1. Node.JS安装笔记

    Node.JS安装笔记 Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an ...

  10. ECharts插件介绍(图表库)

    ECharts是一个非常好用的插件,用于进行 树状图,折线图,饼图,地图等等,系列视图的绘制.(详情看官网) 了解: AMD:模块化开发方式: 引入文件后:console.log(echarts) / ...