• uoj #111. 【APIO2015】Jakarta Skyscrapers


    #111. 【APIO2015】Jakarta Skyscrapers

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

    有 MM 只叫做 “doge” 的神秘生物在雅加达市居住,它们的编号依次是 00 到 M1M−1。编号为 ii 的 doge 最初居住于编号为 BiBi 的摩天楼。每只 doge 都有一种神秘的力量,使它们能够在摩天楼之间跳跃,编号为 ii 的 doge 的跳跃能力为 PiPi (Pi>0Pi>0)。

    在一次跳跃中,位于摩天楼 bb 而跳跃能力为 pp 的 doge 可以跳跃到编号为 bpb−p (如果 0bp<N0≤b−p<N)或 b+pb+p (如果 0b+p<N0≤b+p<N)的摩天楼。

    编号为 00 的 doge 是所有 doge 的首领,它有一条紧急的消息要尽快传送给编 号为 11 的 doge。任何一个收到消息的 doge 有以下两个选择:

    1. 跳跃到其他摩天楼上;
    2. 将消息传递给它当前所在的摩天楼上的其他 doge。

    请帮助 doge 们计算将消息从 00 号 doge 传递到 11 号 doge 所需要的最少总跳跃步数,或者告诉它们消息永远不可能传递到 11 号 doge。

    输入格式

    输入的第一行包含两个整数 NN 和 MM。

    接下来 MM 行,每行包含两个整数 BiBi 和 PiPi。

    输出格式

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

    样例一

    input

    5 3
    0 2
    1 1
    4 1
    
    

    output

    5
    
    

    explanation

    下面是一种步数为 55 的解决方案:

    • 00 号 doge 跳跃到 22 号摩天楼,再跳跃到 44 号摩天楼(22 步)。
    • 00 号 doge 将消息传递给 22 号 doge。
    • 22 号 doge 跳跃到 33 号摩天楼,接着跳跃到 22 号摩天楼,再跳跃到 11 号摩天楼(33 步)。
    • 22 号 doge 将消息传递给 11 号 doge。

    子任务

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

    • 子任务 1 (10 分)
      • 1N101≤N≤10
      • 1Pi101≤Pi≤10
      • 2M32≤M≤3
    • 子任务 2 (12 分)
      • 1N1001≤N≤100
      • 1Pi1001≤Pi≤100
      • 2M20002≤M≤2000
    • 子任务 3 (14 分)
      • 1N20001≤N≤2000
      • 1Pi20001≤Pi≤2000
      • 2M20002≤M≤2000
    • 子任务 4 (21 分)
      • 1N20001≤N≤2000
      • 1Pi20001≤Pi≤2000
      • 2M300002≤M≤30000
    • 子任务 5 (43 分)
      • 1N300001≤N≤30000
      • 1Pi300001≤Pi≤30000
      • 2M300002≤M≤30000

    时间限制1s1s

    空间限制256MB

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<cmath>
    #define maxn 30010
    using namespace std;
    int B,num,tot,s,t,head[maxn*110],m,n,vis[maxn*110],d[maxn*110],pos[110][maxn];
    struct node{int b,p;}a[maxn];
    struct Node{int to,pre,v;}e[maxn*500];
    void Insert(int from,int to,int v){
        e[++num].to=to;
        e[num].v=v;
        e[num].pre=head[from];
        head[from]=num;
    }
    queue<int>q;
    void spfa(){
        for(int i=0;i<=tot;i++)d[i]=1e9,vis[i]=0;
        q.push(a[0].b);
        d[a[0].b]=0;vis[a[0].b]=1;
        while(!q.empty()){
            int x=q.front();q.pop();vis[x]=0;
            for(int i=head[x];i;i=e[i].pre){
                int to=e[i].to;
                if(d[to]>d[x]+e[i].v){
                    d[to]=d[x]+e[i].v;
                    if(!vis[to])q.push(to),vis[to]=1;
                }
            }
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++)scanf("%d%d",&a[i].b,&a[i].p);
        tot=n-1;
        B=min(100,(int)sqrt(n));
        for(int i=1;i<=B;i++)
        for(int j=0;j<i;j++)
        for(int k=j;k<n;k+=i){
            pos[i][k]=++tot;
            Insert(tot,k,0);
            if(k>=i){
                Insert(tot,tot-1,1);
                Insert(tot-1,tot,1);
            }
        }
        for(int i=0;i<m;i++){
            if(a[i].p<=B)
                Insert(a[i].b,pos[a[i].p][a[i].b],0);
            else {
                for(int j=1;;j++)
                    if(j*a[i].p+a[i].b>=n)break;
                    else Insert(a[i].b,j*a[i].p+a[i].b,j);
                for(int j=1;;j++)
                    if(a[i].b-j*a[i].p<0)break;
                    else Insert(a[i].b,a[i].b-j*a[i].p,j);
            }
        }
        spfa();
        if(d[a[1].b]==1e9)puts("-1");
        else printf("%d
    ",d[a[1].b]);
        return 0;
    }
  • 相关阅读:
    docker 知识汇总1-镜像管理
    合并两个git repository
    这一次, 信报箱震惊世界
    python实现括号分组
    linux case菜单代码示例
    oracle 11gR2 client安装(Red Hat Enterprise Linux Server release 5.5 (Tikanga) 安装ORACLE客户端)
    SYSAUX表空间过大处理
    SYSAUX表空间大于33G问题处理
    window 给链接加下划线或取消下划线
    ORACLE11G_win32监听程序不支持服务
  • 原文地址:https://www.cnblogs.com/thmyl/p/8977616.html
Copyright © 2020-2023  润新知