Codeforces Round #225 (Div. 1) B. Volcanoes

B. Volcanoes
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

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.

Sample test(s)
input
4 2
1 3
1 4
output
6
input
7 8
1 6
2 6
3 5
3 6
4 3
5 1
5 2
5 3
output
12
input
2 2
1 2
2 1
output
-1
Note

Consider the first sample. A possible road is: (1, 1)  →  (1, 2)  →  (2, 2)  →  (2, 3)  →  (3, 3)  →  (3, 4)  →  (4, 4).


题意:

给你一个n*n的地图,上面有m个点不能走,你只能往下 和往右走,问能否从(1,1)到达(n,n),能输出步数。

思路:

因为只能往下和往右,所以能达到的话步数就是2*n-2,问题变为判断是否能到达。

因为n很大,所以不能bfs,解题突破口在只能往下和右走,那么只需从上往下找能到达的区间就够了,上一行递推到下一行(这里的行表示出现了Volcanoes的行),比如上一行(4,7)区间能到达,那么下一行如果有(5,9)区间的话,就能到达了。

只考虑出现了Volcanoes的行的话,会产生一个问题,就是如上一行出现了(1,2),中间有空行,后面一行出现了(5,6),那么会发现转移不过来,我的处理方法是这样的空行加一个哨兵点(k,0),那么问题就能解决了。


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 1005
#define MAXN 400005
#define mod 1000000000
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
typedef long long ll;
using namespace std;

int n,m,ans,cnt,tot,flag;
struct Node
{
    int x,y;
}cur,now,p[MAXN],q1[MAXN],q2[MAXN];

bool cmp(Node xx,Node yy)
{
    if(xx.x!=yy.x) return xx.x<yy.x;
    return xx.y<yy.y;
}
bool solve()
{
    int i,j,k,t,nx,ny,x,y,tx,ty,prex;
    int head=0,tail=-1,pt;
    sort(p+1,p+m+1,cmp);
    cnt=0;
    for(i=1;i<=m;i++)  // 加哨兵点
    {
        if(p[i].x-p[i-1].x>1)
        {
            cnt++;
            p[m+cnt].x=p[i].x-1,p[m+cnt].y=0;
        }
    }
    m=m+cnt;
    sort(p+1,p+m+1,cmp);
    cur.x=1,cur.y=1;
    q1[++tail]=cur;
    cnt=0,prex=-1;
    for(i=1;i<=m; )
    {
        while(i<=m&&(prex==-1||p[i].x==prex))  // 将下一行的可行区间取出
        {
            if(prex==-1)
            {
                prex=p[i].x;
                if(p[i].y-1>=1)
                {
                    cnt++;
                    q2[cnt].x=1,q2[cnt].y=p[i].y-1;
                }
            }
            else
            {
                if(p[i].y-1>=p[i-1].y+1)
                {
                    cnt++;
                    q2[cnt].x=p[i-1].y+1,q2[cnt].y=p[i].y-1;
                }
            }
            i++;
        }
        if(p[i-1].y<n)
        {
            cnt++;
            q2[cnt].x=p[i-1].y+1,q2[cnt].y=n;
        }
        pt=tail;
        for(j=1;j<=cnt&&head<=pt;)  // 看这些区间能否到达
        {
            if(q2[j].x>q1[head].y) head++;
            else if(q2[j].x>=q1[head].x&&q2[j].x<=q1[head].y)
            {
                q1[++tail]=q2[j];
                j++;
            }
            else if(q2[j].x<=q1[head].x&&q2[j].y>=q1[head].x)
            {
                cur.x=q1[head].x,cur.y=q2[j].y;
                q1[++tail]=cur;
                j++;
            }
            else j++;
        }
        if(tail==pt) return false ;  // 如果一个点都未更新 说明到此行之后不能走了
        head=pt+1;
        cnt=0,prex=-1;
    }
    if(q1[tail].x<=n&&q1[tail].y>=n) return true ;
    return false ;
}
int main()
{
    int i,j,t;
    while(~scanf("%d%d",&n,&m))
    {
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&p[i].x,&p[i].y);
        }
        m++;
        p[m].x=n,p[m].y=0;
        if(solve()) printf("%d\n",2*n-2);
        else printf("-1\n");
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值