Codeforces383 B. Volcanoes(难题,大矩形能否走到终点)

2024-04-15 23:58

本文主要是介绍Codeforces383 B. Volcanoes(难题,大矩形能否走到终点),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Iahub got lost in a very big desert. The desert can be represented as a n × n square matrix, where each cell is a zone of the desert. The cell (i, j) represents the cell at row i and column j (1 ≤ i, j ≤ n). Iahub can go from one cell (i, j) only down or right, that is to cells (i + 1, j) or (i, j + 1).

Also, there are m cells that are occupied by volcanoes, which Iahub cannot enter.

Iahub is initially at cell (1, 1) and he needs to travel to cell (n, n). Knowing that Iahub needs 1 second to travel from one cell to another, find the minimum time in which he can arrive in cell (n, n).

Input
The first line contains two integers n (1 ≤ n ≤ 109) and m (1 ≤ m ≤ 105). Each of the next m lines contains a pair of integers, x and y (1 ≤ x, y ≤ n), representing the coordinates of the volcanoes.

Consider matrix rows are numbered from 1 to n from top to bottom, and matrix columns are numbered from 1 to n from left to right. There is no volcano in cell (1, 1). No two volcanoes occupy the same location.

Output
Print one integer, the minimum time in which Iahub can arrive at cell (n, n). If no solution exists (there is no path to the final cell), print -1.

Examples
inputCopy
4 2
1 3
1 4
outputCopy
6
inputCopy
7 8
1 6
2 6
3 5
3 6
4 3
5 1
5 2
5 3
outputCopy
12
inputCopy
2 2
1 2
2 1
outputCopy
-1
Note
Consider the first sample. A possible road is: (1, 1)  →  (1, 2)  →  (2, 2)  →  (2, 3)  →  (3, 3)  →  (3, 4)  →  (4, 4).

参考博客1
参考博客2
很难的一道题┭┮﹏┭┮,感谢大佬题解

题意:
1e9*1e9的矩阵,至多1e5个坏点,只能向右向下走,求起点走到终点的最小步数。

思路:
步数肯定是确定的,关键就是能否走到。
肯定是不能直接bfs看能否从起点遍历到终点的,但是坏点数量不大,肯定是要从坏点着手。


直观的方法是将每一列可以到达的区间求出来,然后看最后一列的可行区间是否包含终点。这个方法就是纯模拟区间合并了,对应解法2。


还有一种方法是bfs。可以想到真正影响结果的只有连上边界的坏点,不与连上边界点关联的点,肯定可以直接绕过去。

我们将x=1或者y=n的点放入队列,然后每次将这个点左下(x+1,y-1)的点上面遇到的第一个坏点和右边遇到第一个坏点入队列,如果最后遇到x=n的坏点或者y=1的坏点,那么就走不到终点。

这样队列中每个点(x,y),实际表示了左下角为(x,y),右上角为(1,n)的矩形为不可达矩形(到达了这个部分就出不去了)。从这个矩形下面一行找到往右第一个坏点,左边一列找到往上第一个坏点。相当在这个不可达矩形的基础上,找到周围的坏点,逐步扩大不可达的范围。

当得到x=n的点时,不可达矩形包括了终点。当得到y=1的点是,不可达矩形包括了起点。

这个过程可以用map模拟(这个写法是从参考博客2的博主那里学到的)。

解法1

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <map>
#include <queue>using namespace std;
typedef long long ll;
const int maxn = 1e5 + 7;map<int,map<int,int> >mp1,mp2;
int vis[maxn];struct Node {int x,y;
}a[maxn];int main() {int n,m;scanf("%d%d",&n,&m);queue<int>q;for(int i = 1;i <= m;i++) {scanf("%d%d",&a[i].x,&a[i].y);if(a[i].x == 1 || a[i].y == n) {vis[i] = 1;q.push(i);}mp1[a[i].x][a[i].y] = i;mp2[a[i].y][-a[i].x] = i;}while(!q.empty()) {int now = q.front();q.pop();int x = a[now].x,y = a[now].y;if(x == n || y == 1) {printf("-1\n");return 0;}if(mp1.count(x + 1)) {auto it = mp1[x + 1].lower_bound(y - 1);if(it != mp1[x + 1].end() && !vis[it -> second]) {q.push(it -> second);vis[it -> second] = 1;}}if(mp2.count(y - 1)) {auto it = mp2[y - 1].lower_bound(-(x + 1));if(it != mp2[y - 1].end() && !vis[it -> second]) {q.push(it -> second);vis[it -> second] = 1;}}}printf("%d\n",2 * n - 2);return 0;
}

解法2

#include <cstdio>
#include <cstring>
#include <algorithm>using namespace std;const int maxn = 2e5 + 7;struct Node {int x,y;
}las[maxn],cur[maxn],a[maxn];//上一列的可行区间,当前这一列的可行区间,坏点。
int n,m;int cmp(Node a,Node b) {if(a.y == b.y) return a.x < b.x;return a.y < b.y;
}bool judge() {int cnt = 1;las[0].x = 1;las[0].y = 1;for(int i = 1;i <= m;i++) {if(a[i].y > a[i - 1].y + 1) { //有几列空行,那么区间上界不变,下界变成n。cnt = 1;las[0].y = n;}int k = 0,pre = 0,num = 0;for(k = i + 1;k <= m && a[k].y == a[i].y;k++) {}k--;for(int j = i;j <= k;j++) {if(a[j].x > pre + 1) {cur[num++] = {pre + 1,a[j].x - 1};}pre = a[j].x;}if(n > pre) {cur[num++] = {pre + 1,n};}int t = 0;for(int j = 0;j < cnt;j++) {while(cur[t].x <= las[j].y && t < num) {if(cur[t].y >= las[j].x) {cur[t].x = max(cur[t].x,las[j].x);} else {cur[t].x = cur[t].y = -1;}t++;}if(t >= num) break;}cnt = 0;for(int j = 0;j < t;j++) {if(cur[j].x == -1) continue;las[cnt++] = {cur[j].x,cur[j].y};}if(cnt == 0) {return false;}i = k;}if(a[m].y != n) return true;if(las[cnt - 1].y == n) return true;return false;
}int main() {scanf("%d%d",&n,&m);for(int i = 1;i <= m;i++) {scanf("%d%d",&a[i].x,&a[i].y);}sort(a + 1,a + 1 + m,cmp);if(judge()) printf("%d\n",2 * n - 2);else printf("-1\n");return 0;
}

这篇关于Codeforces383 B. Volcanoes(难题,大矩形能否走到终点)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/907281

相关文章

接口自动化三大经典难题

目录 一、接口项目不生成token怎么解决关联问题 1. Session机制 2. 基于IP或设备ID的绑定 3. 使用OAuth或第三方认证 4. 利用隐式传递的参数 5. 基于时间戳的签名验证 二、接口测试中网络问题导致无法通过怎么办 1. 重试机制 2. 设置超时时间 3. 使用模拟数据 4. 网络问题的预检测 5. 日志记录与错误分析 6. 切换网络环境 7.

光伏项目报告如何做?能否自动生成?

一、光伏项目做报告的必要性 在光伏项目开发过程中,编制一份详尽、准确的光伏项目报告是至关重要的环节。这份报告不仅是对项目建设的全面调查和评估,更是项目立项、审批、融资、设计、建设及运营等多个阶段的重要参考依据。光伏项目报告通过深入分析项目的技术可行性、经济效益、环境影响及社会效益等方面,为项目决策者提供科学、客观的数据支持,从而确保项目的顺利实施和可持续发展。 二、光伏项目报告的内容 光

百度之星初赛1006(计算几何:能包含凸包的最小矩形面积)

矩形面积    Accepts: 717    Submissions: 1619  Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description 小度熊有一个桌面,小度熊剪了很多矩形放在桌面上,小度熊想知道能把这些

NYOJ 16 矩形嵌套

OJ题目 : http://acm.nyist.net/JudgeOnline/problem.php?pid=16 描述 有n个矩形,每个矩形可以用a,b来描述,表示长和宽。矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d(相当于旋转X90度)。例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中。你的任务是选出尽可能多的矩形排成一行,使得除

NYOJ 745 蚂蚁的难题(二)

OJ题目 : http://acm.nyist.net/JudgeOnline/problem.php?pid=745 描述 下雨了,下雨了,蚂蚁搬家了。 已知有n种食材需要搬走,这些食材从1到n依次排成了一个圈。小蚂蚁对每种食材都有一个喜爱程度值Vi,当然,如果Vi小于0的时候,表示蚂蚁讨厌这种食材。因为马上就要下雨了,所以蚂蚁只能搬一次,但是能够搬走连续一段的食材。时间紧急,你快帮

【数据结构-二维前缀和】力扣1504. 统计全 1 子矩形

给你一个 m x n 的二进制矩阵 mat ,请你返回有多少个 子矩形 的元素全部都是 1 。 示例 1: 输入:mat = [[1,0,1],[1,1,0],[1,1,0]] 输出:13 解释: 有 6 个 1x1 的矩形。 有 2 个 1x2 的矩形。 有 3 个 2x1 的矩形。 有 1 个 2x2 的矩形。 有 1 个 3x1 的矩形。 矩形数目总共 = 6 + 2 + 3 + 1 +

函数能否返回对象,而不是指针

现有一通用 获取记录集合函数 function GetRec(StrSql:string):Tadodataset; var rec1:Tadodataset; begin rec1:=TADODataSet.Create(nil); rec1.Connection:=ADOConnection1; rec1.CommandText:=strsql; rec1.Open; result:=rec1

牛客网《剑指Offer》 矩形覆盖

题目描述 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? class Solution {public:int rectCover(int number) {if(number==0) return 0;if(number==1) return 1;if(number==2) return 2;retu

【每日一题】LeetCode 84.柱状图中最大的矩形(栈、数组、单调栈)

【每日一题】LeetCode 84.柱状图中最大的矩形(栈、数组、单调栈) 题目描述 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。 这个题目和接雨水非常类似 点击跳转接雨水 LeetCode 40.接雨水 输入示例 输入:heights = [2,1,5,6,2,3] 输出:10 解释:最大的

OpenCV 旋转矩形边界

边界矩形是用最小面积绘制的,所以它也考虑了旋转。使用的函数是**cv.minAreaRect**()。 import cv2import numpy as npimg=cv2.imread(r'D:\PythonProject\thunder.jpg')img1=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)print(img.dtype)ret,thres