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. nginx坑记录

    问题1: 配置解析过程使用ngx_cycle->pool申请内存保存配置,结果造成野指针. 背景:需求开发过程,有一些结构需要在配置解析阶段保存,然后可以动态修改.看原来的代码配置解析都是使用c ...

  2. 并发测试JMeter及发送Json请求

    1.下载 提前安装好jdk1.8 官网下载地址:http://jmeter.apache.org/download_jmeter.cgi 2.解压,双击bin/jmeter.bat 3.jmeter配 ...

  3. 测开之路九十三:css之文字样式和段落对齐

    引用css 字体族 字体类型和尺寸 em:字体按倍数缩放 font-weight:调整文字的粗细 段落对齐:text-align 左对齐:left 右对齐:right 居中对齐:center 两边对齐 ...

  4. UI自动化之js\jquery的应用

    js\jquery的应用,有很多难以定位到的,可以通过js或者jquery来处理 目录 1.js 2.jquery 1.js 1.1js有5种定位,最后execute_script(js)来执行js ...

  5. sprint test 添加事务回滚机制

    1.原因: 单元测试的时候频繁操作数据库需要修改很多数据,造成不必要的操作,添加事务之后就可以重复对一条数据进行操作,并且在返回结果后进行回滚. 2.解决: 原先继承的是  AbstractJUnit ...

  6. source ~/.bash_profile是什么意思

    ~ 这个符号表示你的家目录,.bash_profile 是一个隐藏文件,主要是用来配置bash shell的,source -/.bash_profile 就是让这个配置文件在修改后立即生效.

  7. new Date() 对象及方法:

    在别人的代码中见了两回 new Date().toLocaleString(),查了才知道,toLocaleString()是 根据本地时间格式,把 Date 对象转换为字符串.于是好奇new Dat ...

  8. 前端 CSS的选择器 伪元素选择器

    介绍常用的伪元素. after用得比较多的 first-letter 用于为文本的第一个首字母设置样式. <!DOCTYPE html> <html lang="en&qu ...

  9. Java相关面试题总结+答案(五)

    [异常] 74. throw 和 throws 的区别? throw 是真实抛出一个异常: throws 是声明可能会抛出一个异常. 75. final.finally.finalize 有什么区别? ...

  10. centos7下搭建Testlink环境详细过程

    花了半天的时间终于搭建好了完整的Testlink环境,主要包括Mysql以及PHP的版本.未关闭防火墙.以及安装配置过程中遇到的一些问题.以下是详细的搭建过程. 一.工具准备 以下是我在搭建过程中用到 ...