[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. Django框架架构总览

    Django框架架构总览 理解Django是如何运作的 条目创建于 2013-08-14     1464 views     服务器君一共花费 15.204 ms 进行了 4 次数据库查询,努力地为 ...

  2. 机器学习中的偏差(bias)和方差(variance)

    转发:http://blog.csdn.net/mingtian715/article/details/53789487请移步原文 内容参见stanford课程<机器学习>   对于已建立 ...

  3. Rosetta Stone 不在C盘安装步骤

    本文出自:http://www.cnblogs.com/2186009311CFF/p/7500637.html Rosetta Stone默认安装在C盘的,很不好,故找到次解决方案: 总体就是移动文 ...

  4. 开发工具Intellij IDEA:面板介绍

    一.面板说明 IDEA面板的全貌如下图 2|0 二.菜单栏 下面会简单介绍下一些常用的部分菜单使用,如有疑问或补充欢迎留言. (1).File文件 1. New:新建一个工程 可以新建project, ...

  5. leetcode打卡

    leetcode刷题打卡 刷题链接 夸夸群 刷题记录链接 期中颜色不一样的,是刷题中遇到问题的,以后需要强化 [x] 6.1 打卡 [x] 6.2 打卡 中间因个人原因没做题,后面慢慢补上 [x] 6 ...

  6. 纯CSS手动滑动轮播图(隐藏滚动条)

    HTML: <div class="bigder"> <div class="big"> <dl> <dt>&l ...

  7. 转载:PICT使用教程(设计测试用例工具)

    原文:https://blog.csdn.net/quiet_girl/article/details/50699543 之前一篇写了正交设计助手的使用教程,与正交设计助手相比,个人觉得PICT的使用 ...

  8. lambda匿名函数和内置函数

    对于简单的函数,也存在一种简便的表示方式,即:lambda表达式 定义函数(普通方式) def func(arg):     return arg + 1      执行函数 result = fun ...

  9. netflow-module

    https://www.elastic.co/guide/en/logstash/current/netflow-module.html

  10. day57——ajax之初体验

    转行学开发,代码100天——2018-05-12 今天是一个特别的日子——首先是母亲节,在此也祝福亲爱的妈妈健康长寿.其次今天是汶川大地震10周年,10年过去了,经历过苦难的人更加坚毅勇敢地面向未来! ...