uoj #111. 【APIO2015】Jakarta Skyscrapers

#111. 【APIO2015】Jakarta Skyscrapers

印尼首都雅加達市有 NN 座摩天樓,它們排列成一條直線,咱們從左到右依次將它們編號爲 00 到 N1N−1。除了這 NN 座摩天樓外,雅加達市沒有其餘摩天樓。node

有 MM 只叫作 「doge」 的神祕生物在雅加達市居住,它們的編號依次是 00 到 M1M−1。編號爲 ii 的 doge 最初居住於編號爲 BiBi 的摩天樓。每隻 doge 都有一種神祕的力量,使它們可以在摩天樓之間跳躍,編號爲 ii 的 doge 的跳躍能力爲 PiPi (Pi>0Pi>0)。ios

在一次跳躍中,位於摩天樓 bb 而跳躍能力爲 pp 的 doge 能夠跳躍到編號爲 bpb−p (若是 0bp<N0≤b−p<N)或 b+pb+p (若是 0b+p<N0≤b+p<N)的摩天樓。atom

編號爲 00 的 doge 是全部 doge 的首領,它有一條緊急的消息要儘快傳送給編 號爲 11 的 doge。任何一個收到消息的 doge 有如下兩個選擇:spa

  1. 跳躍到其餘摩天樓上;
  2. 將消息傳遞給它當前所在的摩天樓上的其餘 doge。

請幫助 doge 們計算將消息從 00 號 doge 傳遞到 11 號 doge 所須要的最少總跳躍步數,或者告訴它們消息永遠不可能傳遞到 11 號 doge。code

輸入格式

輸入的第一行包含兩個整數 NN 和 MM。xml

接下來 MM 行,每行包含兩個整數 BiBi 和 PiPi。blog

輸出格式

輸出一行,表示所須要的最少步數。若是消息永遠沒法傳遞到 11 號 doge,輸出 1−1。input

樣例一

input

5 3
0 2
1 1
4 1

output

5

explanation

下面是一種步數爲 55 的解決方案:string

  • 00 號 doge 跳躍到 22 號摩天樓,再跳躍到 44 號摩天樓(22 步)。
  • 00 號 doge 將消息傳遞給 22 號 doge。
  • 22 號 doge 跳躍到 33 號摩天樓,接着跳躍到 22 號摩天樓,再跳躍到 11 號摩天樓(33 步)。
  • 22 號 doge 將消息傳遞給 11 號 doge。

子任務

全部數據都保證 0Bi<N0≤Bi<N。io

  • 子任務 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\n",d[a[1].b]);
    return 0;
}
相關文章
相關標籤/搜索