1. 程式人生 > >題解[AHOI2002]哈利·波特與魔法石

題解[AHOI2002]哈利·波特與魔法石

pty problem printf {0} main ret 建立 題解 一道

題目傳送門
這是一道很經典的最短路問題

因為數據範圍較小,所以不用鄰接表的SPFA也不會MLE

#include<bits/stdc++.h>
using namespace std;
int a[120][120];
//a[i][j]代表從i到j的路程(-1表示沒路)
int h[8] = {0,2,6,4,8,6,10,14};
//h代表每種地形所需時間
queue<int> q; //隊列
int s,e;//起點和終點
int dis[120]; //dis[i]代表點i到起點的最短時間
bool used[120] = {0}; //防止元素重復入隊
int main(){
    memset(a,-1,sizeof(a));
    memset(dis,-1,sizeof(dis));
    bool flag;
    for(int i = 1;i<=7;i++){
        scanf("%d",&flag);
        if(flag==1)h[i]/=2;
    }//如果有魔法石則時間減半
    scanf("%d%d",&s,&e);
    int n;
    scanf("%d",&n);
    int ai,bi,ti;
    for(int i = 1;i<=n;i++){
        scanf("%d%d%d",&ai,&bi,&ti);
        a[ai][bi] = h[ti];
        a[bi][ai] = h[ti];
        //註意是無向圖,要建立雙向邊(如果不建立雙向邊只有20分,我為此提交了4遍才過)
    }
    q.push(s);
    //起點入隊
    dis[s] = 0;
    while(!q.empty()){ // 裸的SPFA
        int nw = q.front();
        for(int i = 1;i<=101;i++){
            if(a[nw][i]==-1)continue;
            int rd = dis[nw]+a[nw][i];//rd為經過nw到a的最短時間
            if(dis[i]==-1){ //如果這個點是第一次搜索到
                dis[i] = rd;
                q.push(i);
                used[i] = 1;
            }else{ //否則比較dis[i]和rd大小
                if(dis[i]<=rd)continue;
                dis[i] = rd;
                if(!used[i]){
                    q.push(i);
                    used[i] = 1;
                }
            }
        }
        q.pop();    
        used[nw] = 0;
    }
    printf("%d",dis[e]);
    //輸出終點到起點的最短時間
    return 0;
}

題解[AHOI2002]哈利·波特與魔法石