http://codeforces.com/contest/1201/problem/D

题意:n行m列的矩阵中,有k个targets,从[1, 1]出发,每次只能向上下左右四个方向移动一步,且只有在q个safecolumns上进行向上移动,最少需要多少次移动才能获得所有的targets。(2≤n,m,k,q≤2*10^5,q≤m)。

  

思路:

Make two arrays: left and right. left[i] is the treasure in the leftmost position in row i (0 if there are no treasures in row ii). right[i] is the treasure in the rightmost cell in row ii (0 if there are no treasures in row ii).

We can simply take out rows where there is no treasure (and add 1 to the result if there are treasure above that line, because we have to move up there).

For every row, except the last, we have to leave that row at one of the safe columns. Let's notice that the last treasure we collect in the row will be either left[i] or right[i]. Let's take a look at both possibilities: If we collect the left[i] treasure last, we have to leave the row either going left or going right to the closest safe column, because going further wouldn't worth it (consider moving up earlier and keep doing the same thing at row i+1). The same is true for right[i]. For the first row, we start at the first column, we can calculate the moves required to go up the second row at the for cells. For all the other rows, we have 4 possibilities, and we have to calculate how many moves it takes to reach the row i+1 at the 4 possible columns. For the last row, we don't have to reach a safe column, we just have to collect all the treasures there. We can count the answer for the problem from the calculated results from the previous row. Time complexity: O(16∗n)

1. 对于存在宝藏的行,最后得到的宝藏要么是最左边的要么是最右边的;

2. 假设最后拿到的是最左边的,那么可以通过这个宝藏左右最近的safecolumns离开;最后拿到的是最右边的情况也同理;

3. 对于第一行来说,若有宝藏,则获得最右边的宝藏后离开;所无宝藏,则通过离[1, 1]最近的safecolumn离开;

4. 对于其他行来说,最多可以有四种方式离开此行,最后一行不需要到达safecolumn,获得所有宝藏即可;

宝藏左右最近的safecolumn,可以通过binary search求得。

注意,若最左边的宝藏就在safecolumn上,则其左右最近的safecolumn都是此列。

#include <iostream>
#include <set>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std; typedef long long LL; int findSafe(vector<int>& safes, int x){
int l = , r = safes.size()-, ret;
while(l <= r){
int m = (l+r)>>;
if(safes[m] == x)
return m;
if(safes[m] > x)
r = m - ;
else{
ret = m;
l = m + ;
}
}
return ret;
} int dist(int layer, int p1, int p2, vector<int>& leftmost, vector<int>& rightmost, vector<int>& safecol){
if(safecol[p1] > safecol[p2])
swap(p1, p2);
int d = safecol[p2] - safecol[p1];
if(rightmost[layer] > safecol[p2])
d += * (rightmost[layer]-safecol[p2]);
if(leftmost[layer] < safecol[p1])
d += * (safecol[p1]-leftmost[layer]);
return d;
} int main(){
int n, k, m, q;
cin>>n>>m>>k>>q;
vector<int> leftmost(n+, m+), rightmost(n+, ), safecol{};
for(int i=; i<k; i++){
int row, col;
cin>>row>>col;
leftmost[row] = min(leftmost[row], col);
rightmost[row] = max(rightmost[row], col);
}
for(int i=; i<q; i++){
int safe;
cin>>safe;
safecol.push_back(safe);
} sort(safecol.begin(), safecol.end()); while(leftmost[n] == m+) n--; if(n==){
cout<<rightmost[]-<<endl;
return ;
}
vector<LL> now_step{, , ,}, lst_step{, , , };
vector<int> lst_gate{-, -, -, -};
if(rightmost[] == ){
int rsafe = findSafe(safecol, );
if(safecol[rsafe] < )
rsafe++;
lst_gate[] = rsafe;
lst_step[] = safecol[rsafe]-;
}else{
int lsafe = findSafe(safecol, rightmost[]);
//cout<<rightmost[1]<<"*"<<lsafe<<endl;
lst_gate[] = lsafe;
lst_step[] = *rightmost[]-safecol[lsafe]-;
//cout<<"l10:"<<lst_step[0]<<endl;
if(safecol[lsafe]<rightmost[] && lsafe+ < safecol.size()){
lst_gate[] = lsafe+;
lst_step[] = safecol[lsafe+]-;
}
} for(int i=; i<n; i++){
if(leftmost[i] == m+){
for(int j=; j<; j++)
lst_step[j]++;
continue;
}else{
vector<int> now_gate{-, -, -, -};
int g1 = findSafe(safecol, leftmost[i]);
int g2 = findSafe(safecol, rightmost[i]);
//cout<<g1<<" "<<g2<<endl;
now_gate[] = g1;
if(safecol[g1] < leftmost[i] && g1+ < safecol.size())
now_gate[] = g1+;
now_gate[] = g2;
if(safecol[g2] < rightmost[i] && g2+ < safecol.size())
now_gate[] = g2+;
for(int j=; j<; j++){
now_step[j] = (*1e5+) * (*1e5);
for(int u=; u<; u++)
if(lst_gate[u]> && now_gate[j]>){
int d = +dist(i,now_gate[j], lst_gate[u], leftmost, rightmost, safecol);
//cout<<now_gate[j]<<" "<<lst_gate[u]<<endl;
//cout<<"d:"<<i<<" "<<d<<endl;
//cout<<"ld:"<<" "<<lst_step[u]<<endl;
now_step[j] = min(now_step[j], lst_step[u]+d);
}
}
lst_step = now_step;
lst_gate = now_gate;
}
}
LL ret = (*1e5+) * (*1e5);
for(int u=; u<; u++)
if(lst_gate[u] > ){
int d = +rightmost[n]-leftmost[n]+min(abs(rightmost[n]-safecol[lst_gate[u]]), abs(leftmost[n]-safecol[lst_gate[u]]));
//cout<<"d:"<<" "<<d<<endl;
//cout<<"lst_step:"<<lst_step[u]<<endl;
ret = min(ret, lst_step[u]+d);
}
printf("%I64d\n", ret);
return ;
}

codeforces_D. Treasure Hunting_[DP+Binary Search]的更多相关文章

  1. 96. Unique Binary Search Trees (Tree; DP)

    Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...

  2. Unique Binary Search Trees(dp)

    Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...

  3. Unique Binary Search Trees I&II——给定n有多少种BST可能、DP

    Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...

  4. [LeetCode] Unique Binary Search Trees 独一无二的二叉搜索树

    Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...

  5. [LeetCode] Unique Binary Search Trees II 独一无二的二叉搜索树之二

    Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. For e ...

  6. Leetcode 86. Unique Binary Search Trees

    本题利用BST的特性来用DP求解.由于BST的性质,所以root左子树的node全部<root.而右子树的node全部>root. 左子树 = [1, j-1], root = j, 右子 ...

  7. Unique Binary Search Trees

    Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...

  8. LeetCode-96. Unique Binary Search Trees

    Description: Given n, how many structurally unique BST's (binary search trees) that store values 1.. ...

  9. LeeCode - Unique Binary Search Trees

    题目: Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For e ...

随机推荐

  1. 使用spring提供的@Scheduled注解创建定时任务

    使用方法 操作非常简单,只要按如下几个步骤配置即可 1. 导入jar包或添加依赖,其实定时任务只需要spring-context即可,当然起服务还需要spring-web: 2. 编写定时任务类和方法 ...

  2. Delphi XE2 之 FireMonkey 入门(29) - 数据绑定: TBindingsList: 表达式的 Evaluate() 方法

    Delphi XE2 之 FireMonkey 入门(29) - 数据绑定: TBindingsList: 表达式的 Evaluate() 方法 TBindingsList 中可能不止一个表达式, 通 ...

  3. golang md5 结果类型

    golang  md5 结果类型 package main import ( "crypto/md5" "encoding/hex" "fmt&quo ...

  4. C++笔记(2)——一些语法基础知识以及基本算法知识

    今天和PAT无直接相关的关系,主要是关于一些语法/算法的笔记,因为我发现自己的基础还没有打扎实,有些时候看别人的代码还会觉得一头雾水,不明白代码的含义. 一些C/C++语法 先从语法开始吧.这部分很琐 ...

  5. State Function Approximation: Linear Function

    In the previous posts, we use different techniques to build and keep updating State-Action tables. B ...

  6. Tensorflow实战 手写数字识别(Tensorboard可视化)

    一.前言 为了更好的理解Neural Network,本文使用Tensorflow实现一个最简单的神经网络,然后使用MNIST数据集进行测试.同时使用Tensorboard对训练过程进行可视化,算是打 ...

  7. ntp局域网时间同步操作

    需求:局域网里面有两台电脑需要同步时间 一台windows,一台Linux.把windows当作服务器 windows10自带ntp服务器,可以按如下步骤进行设置 1. 打开注册表编辑器,在运行里面输 ...

  8. 日记smarthome

    测试命令:测试命令 7e 7e 两个字节 一个字节  两个字节 一个字节     解释: 两个字节是userid的值 int Userid = data[i] * 256 + data[i + 1]; ...

  9. Codeforces 1042C (贪心+模拟)

    题面 传送门 分析 思路简单,但代码较复杂的贪心 分类讨论: 有0 负数有奇数个:将绝对值最小(实际最大)的负数和0全部乘到一起,最后删掉0 负数有偶数个:将0全部乘到一起,最后删掉0 没有0 负数有 ...

  10. Javascript 中的深浅拷贝

    工作中经常会遇到需要复制 JS 数据的时候,遇到 bug 时实在令人头疼:面试中也经常会被问到如何实现一个数据的深浅拷贝,但是你对其中的原理清晰吗?一起来看一下吧! 为什么会有深浅拷贝 想要更加透彻的 ...