zoukankan      html  css  js  c++  java
  • bzoj 4070 [Apio2015]雅加达的摩天楼 Dijkstra+建图

    [Apio2015]雅加达的摩天楼

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 644  Solved: 238
    [Submit][Status][Discuss]

    Description

     印尼首都雅加达市有 N 座摩天楼,它们排列成一条直线,我们从左到右依次将它们编号为 0 到 N−1。除了这 N 座摩天楼外,雅加达市没有其他摩天楼。

     
    有 M 只叫做 “doge” 的神秘生物在雅加达市居住,它们的编号依次是 0 到 M−1。编号为 i 的 doge 最初居住于编号为 Bi 的摩天楼。每只 doge 都有一种神秘的力量,使它们能够在摩天楼之间跳跃,编号为 i 的 doge 的跳跃能力为 Pi (Pi>0)。
     
    在一次跳跃中,位于摩天楼 b 而跳跃能力为 p 的 doge 可以跳跃到编号为 b−p (如果 0≤b−p<N)或 b+p (如果 0≤b+p<N)的摩天楼。
     
    编号为 0 的 doge 是所有 doge 的首领,它有一条紧急的消息要尽快传送给编 号为 1 的 doge。任何一个收到消息的 doge 有以下两个选择:
     
    跳跃到其他摩天楼上;
    将消息传递给它当前所在的摩天楼上的其他 doge。
    请帮助 doge 们计算将消息从 0 号 doge 传递到 1 号 doge 所需要的最少总跳跃步数,或者告诉它们消息永远不可能传递到 1 号 doge。
     

    Input

    输入的第一行包含两个整数 N 和 M。

     
    接下来 M 行,每行包含两个整数 Bi 和 Pi。
     

    Output

    输出一行,表示所需要的最少步数。如果消息永远无法传递到 1 号 doge,输出 −1。

     

    Sample Input

    5 3
    0 2
    1 1
    4 1

    Sample Output

    5
    explanation
    下面是一种步数为 5 的解决方案:
    0 号 doge 跳跃到 2 号摩天楼,再跳跃到 4 号摩天楼(2 步)。
    0 号 doge 将消息传递给 2 号 doge。
    2 号 doge 跳跃到 3 号摩天楼,接着跳跃到 2 号摩天楼,再跳跃到 1 号摩天楼(3 步)。
    2 号 doge 将消息传递给 1 号 doge。

    HINT

     子任务


    所有数据都保证 0≤Bi<N。

     

    子任务 1 (10 分)

    1≤N≤10

    1≤Pi≤10

    2≤M≤3

    子任务 2 (12 分)

    1≤N≤100

    1≤Pi≤100

    2≤M≤2000

    子任务 3 (14 分)

    1≤N≤2000

    1≤Pi≤2000

    2≤M≤2000

    子任务 4 (21 分)

    1≤N≤2000

    1≤Pi≤2000

    2≤M≤30000

    子任务 5 (43 分)

    1≤N≤30000

    1≤Pi≤30000

    2≤M≤30000

    题目看起来就像最短路,但是建图十分棘手,可以思考一下分块,当时想的时候并不怎么

    会,设p为块的大小,对于大于p的话,最多只有n/p的边,直接暴力建边就可以了,对于剩

    下的边,我们分层,分出p层,第i层,向其左右距离为i的点连边,每一层向最底层连边,这

    样,当一个点的跳跃距离为x<=p时,最底层向x层连边,最后判断一下最底层然后就可以了,

    具体的花费时间考虑一下没什么问题,然后当p取根号的时候比较优秀吧,Dijkstra就好了。

     1 #include<cstring>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<queue>
     7 
     8 #define F(i,j,n) for(int i=j;i<=n;i++)  
     9 #define D(i,j,n) for(int i=j;i>=n;i--)  
    10 #define ll long long  
    11 #define maxn 30005*105  
    12 #define maxm 30005*500  
    13 #define inf 1000000000  
    14 using namespace std;
    15 inline int read()
    16 {
    17     int x=0,f=1;char ch=getchar();
    18     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    19     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    20     return x*f;
    21 }
    22 
    23 int n,m,s,t,tot,tmp;  
    24 int b[30005],p[30005],head[maxn],dis[maxn];  
    25 bool inq[maxn];  
    26 struct edge_type{int next,to,v;}e[maxm];  
    27 queue<int> q;  
    28 
    29 inline void add_edge(int x,int y,int v)  
    30 {  
    31     e[++tot]=(edge_type){head[x],y,v};head[x]=tot;  
    32 }  
    33 inline void spfa()  
    34 {  
    35     memset(dis,-1,sizeof(dis));  
    36     dis[s]=0;q.push(s);inq[s]=true;  
    37     while (!q.empty())  
    38     {  
    39         int x=q.front();q.pop();inq[x]=false;  
    40         for(int i=head[x];i;i=e[i].next)  
    41         {  
    42             int y=e[i].to;  
    43             if (dis[y]==-1||dis[y]>dis[x]+e[i].v)  
    44             {  
    45                 dis[y]=dis[x]+e[i].v;  
    46                 if (!inq[y]) q.push(y),inq[y]=true;  
    47             }  
    48         }  
    49     }  
    50 }  
    51 inline int num(int x,int y)  
    52 {  
    53     return x*n+y;  
    54 }  
    55 int main()  
    56 {  
    57     n=read();m=read();  
    58     F(i,1,m) b[i]=read()+1,p[i]=read();  
    59     s=b[1];t=b[2];  
    60     tmp=min((int)sqrt(n),100);  
    61     F(i,1,tmp) F(j,1,n) add_edge(num(i,j),j,0);  
    62     F(i,1,tmp) F(j,1,n-i) add_edge(num(i,j),num(i,j+i),1),add_edge(num(i,j+i),num(i,j),1);  
    63     F(i,1,m)  
    64     {  
    65         if (p[i]<=tmp) add_edge(b[i],num(p[i],b[i]),0);  
    66         else  
    67         {  
    68             for(int j=1;b[i]+j*p[i]<=n;j++) add_edge(b[i],b[i]+j*p[i],j);  
    69             for(int j=1;b[i]-j*p[i]>=1;j++) add_edge(b[i],b[i]-j*p[i],j);  
    70         }  
    71     }  
    72     spfa();  
    73     printf("%d
    ",dis[t]);  
    74 }  
  • 相关阅读:
    ORA-02020 : 过多的数据库链接在使用中-Windows环境解决步骤
    <转载>c++中new一个二维数组
    C C++输出格式 <转载>仅用于个人
    *p 和p[i] 区别
    Const *ptr ptr
    C 格式化的输入输出(printf scanf)
    PP 各种快捷键
    【Java并发工具类】原子类
    【Java并发工具类】Java并发容器
    【Java并发工具类】CountDownLatch和CyclicBarrier
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8759271.html
Copyright © 2011-2022 走看看