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

这个一场div2 前面三题特别简单,这个D题的dp还是比较难的,不过题目告诉你了只能往上走,所以还是可以看出来这个是一个dp的。

然后对于每一段,肯定是从左到右或者从右到左这个是最优的,这里就是有一点点贪心的思想。

所以要我们首先要求出每一行的最大最小,然后就是开始转移。

题目要求只有一部分的列才可以竖直方向的走,这个让我就有点迷糊。

首先每一段向下转移,如果这个位置向下转移到的那个位置直接有直线可以竖着的走,

那么可以知道这个肯定是最优的,如果没有就只能找两边的了。

这个其实有点难写,看了别人的代码发现,这个可以用lower_bound 和 upper_bound 很巧妙的解决。

首先在一个数组里面存下可以走的每一列,然后还要存一个最小值-inf,和一个最大值 inf。然后排序一下。

然后就是找对于每一个区间,就是刚刚说的那个转移区间,(x,y) 注意 x不一定小于等于y

我们开始用lower_bound 找到大于等于x的最大值,如果没有大于等于x的那么就会找到inf,这个很自然会被舍去,然后upper_bound 就会找到区间左边的,

如果找到了大于等于的,那么用upper_bound会找到相同的位置,然后-1就是区间左边的,这个时候就判断一下,选哪个更优。

如果y>y 也是一样的,这个lower_bound 会找到两边的,如果中间有那么upper_bound也会找到。

这个之后还要加一点点东西,竖直距离和max[i]-min[i]

#include <cstring>
#include <queue>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 2e5 + ;
typedef long long ll;
int Max[maxn], Min[maxn], num[maxn], cnt;
ll dp[maxn][]; ll dis(int x,int y)
{
int l = *(lower_bound(num + , num + + cnt, x));
int r = *(upper_bound(num + , num + + cnt, x) - );
return min(abs(x - l) + abs(y - l), abs(x - r) + abs(y - r));
} int main()
{
int n, m, k, q, ans = ;
scanf("%d%d%d%d", &n, &m, &k, &q);
memset(Min, inf, sizeof(Min));
for(int i=;i<=k;i++)
{
int l, r;
scanf("%d%d", &l, &r);
Max[l] = max(Max[l], r);
Min[l] = min(Min[l], r);
ans = max(ans, l);
}
for(int i=;i<=q;i++)
{
int x;
scanf("%d", &x);
num[i] = x;
}
cnt = q;
num[++cnt] = inf; num[++cnt] = -inf;
sort(num + , num + + cnt);
if(Max[]==) Max[] = , Min[] = ;
dp[][] = Max[] * - Min[] - ;
dp[][] = Max[] - ;
//printf("ww %lld %lld\n", dp[1][0], dp[1][1]);
int x = ;
for(int i=;i<=n;i++)
{
//printf("i=%d\n", i);
if (Max[i] == ) continue;
dp[i][] = min(dis(Min[x], Max[i]) + dp[x][], dis(Max[x], Max[i]) + dp[x][]);
dp[i][] = min(dis(Min[x], Min[i]) + dp[x][], dis(Max[x], Min[i]) + dp[x][]);
//printf("dp[%d][0]=%lld dp[%d][1]=%lld\n", i, dp[i][0], i, dp[i][1]);
dp[i][] += abs(Max[i] - Min[i]) + i - x;
dp[i][] += abs(Max[i] - Min[i]) + i - x;
x = i;
//printf("dp[%d][0]=%lld dp[%d][1]=%lld\n", i, dp[i][0], i, dp[i][1]);
}
//printf("ans=%d\n", ans);
printf("%lld\n", min(dp[ans][], dp[ans][]));
return ;
}

最新文章

  1. 在Windows上编译和调试CoreCLR
  2. CYQ.Data V5 从入门到放弃ORM系列:教程 - Log、SysLogs两个日志类使用
  3. Jquery中ajax方法data参数的用法
  4. sp_MSforeachtable 与 sp_MSforeachdb
  5. windows下PHP批量生成打包android程序APK-渠道txt植入apk文件
  6. Facebook is Hiring!
  7. Brief introduction to Scala and Breeze for statistical computing
  8. JS-001-单选复选按钮操作
  9. [xml解析]rapidxml读取文件
  10. C11 memory_order
  11. wkhtmltopdf 生成pdf
  12. (中等) POJ 2528 Mayor&#39;s posters , 离散+线段树。
  13. iOS 正则表达式使用(转)
  14. Django+nginx+uwsgi部署教程(centos7+ubuntu16.4)
  15. 如何在Android上编写高效的Java代码
  16. 【Java】【11】String数组和List相互转换
  17. vue-axios的application/x-www-form-urlencod的post请求无法解析参数
  18. android --------- 嵌套unity出现 your hardware does not support this application,sorry!
  19. skipper http router 工具
  20. slice.indices()/collections.Counter笔记

热门文章

  1. MODIS系列之NDVI(MOD13Q1)四:MRT单次及批次处理数据
  2. java web之Filter详解
  3. [算法]素数筛法(埃氏筛法&amp;线性筛法)
  4. 【Java】步入OOP 面向对象
  5. work of 12/30/2015
  6. 掌握MySQL连接查询到底什么是驱动表
  7. Apache solr velocity模块 漏洞复现
  8. 【论文笔记】YOLOv4: Optimal Speed and Accuracy of Object Detection
  9. Junit借助Groboutils Core进行并发测试
  10. tp5--相对路径和绝对路径