codeforces_D. Treasure Hunting_[DP+Binary Search]
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]的更多相关文章
- 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 ...
- Unique Binary Search Trees(dp)
Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...
- 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 ...
- [LeetCode] Unique Binary Search Trees 独一无二的二叉搜索树
Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...
- [LeetCode] Unique Binary Search Trees II 独一无二的二叉搜索树之二
Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. For e ...
- Leetcode 86. Unique Binary Search Trees
本题利用BST的特性来用DP求解.由于BST的性质,所以root左子树的node全部<root.而右子树的node全部>root. 左子树 = [1, j-1], root = j, 右子 ...
- Unique Binary Search Trees
Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...
- LeetCode-96. Unique Binary Search Trees
Description: Given n, how many structurally unique BST's (binary search trees) that store values 1.. ...
- LeeCode - Unique Binary Search Trees
题目: Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For e ...
随机推荐
- curl 使用 post 请求,传递 json 参数,下载文件
curl -X POST http://ip:8888/nacos/v1/cs/file/download -H "Accept: application/octet-stream" ...
- 阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第5节 String类_3_字符串的常量池
字符换是可以共享使用的,那么怎么去共享使用呢 三种方式去创建字符串.然后三种分别进行比较 3的地址和1.2的地址不一样 在堆里面有一块空间叫做字符串常量池,从jdk1.7开始.字符串常量池在堆中 字符 ...
- Week 7 - 714. Best Time to Buy and Sell Stock with Transaction Fee & 718. Maximum Length of Repeated Subarray
714. Best Time to Buy and Sell Stock with Transaction Fee - Medium Your are given an array of intege ...
- python 设置开机启动脚本
1.创建python_auto.bat的快捷方式,放入启动项: C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\ ...
- Delphi MlSkin V1.1 发布啦! 它能让你的程序拥有像QQ一样多彩炫丽的外观!
http://bbs.csdn.net/topics/390740239 本帖最后由 u014161811 于 2014-03-24 09:46:40 编辑 QQ皮肤透明TEdit透明TMemo图片按 ...
- maven(一) maven到底是什么
为了方便自己查找,这里转载他人文章,原文出处http://www.cnblogs.com/whgk/p/7112560.html 我记得在搞懂maven之前看了几次重复的maven的教学视频.不知道是 ...
- winform项目中开发的一套UI控件库
https://github.com/houyhea/winform-control-lib winform-control-lib 曾经在一个winform项目中开发的一套UI控件库 类图: 效果 ...
- WPF资源字典的使用
1.在解决方案中添加资源字典:鼠标右键——添加——资源字典 2.在资源字典中写入你需要的样式,我这里简单的写了一个窗体的边框样式 3.在App.xaml中加入刚刚新建的资源字典就好了
- (136)leetcode刷题Python笔记——只出现一次的数字
题目如下: 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 说明: 你的算法应该具有线性时间复杂度. 你可以不使用额外空间来实现吗? 示例 1: ...
- Oracle创建表 创建库 数据恢复
--建用户CREATE USER szs IDENTIFIED BY szs DEFAULT TABLESPACE NN_DATA01 TEMPORARY TABLESPACE temp;--用户赋权 ...