poj-1062(昂貴的婚禮)

前兩天集訓的時候現場賽考到這道題,一開始看到是中文的,心裏那個激動啊,簡直難以言表,然後我就埋頭看了一下題,幾分鐘後,心裏千萬只草泥馬在奔騰,這題在講什麼鬼,沒看懂,這種感覺簡直難以言表。趕緊切題,最後到比賽結束還是沒想出來。過了兩天,重新看這道題,好像有點明白了,個人感覺這道題相當不錯。

題目大意:這道題雖然是中文題,但有些地方需要理解一下。總共有 N 個物品,對着N個物品從 1 到 N 編號,每個物品有 X 個替代品,比如樣例所給的 1 號物品有兩個替代品,其中一個編號爲 2,表示用 2 號物品再加上8000元可以得到 1 號物品,其它類似(當初看到樣例愣是沒想到有什麼聯繫敲打)。然後題目問最少用多少金幣可以得到1號物品,注意題目中有一個等級限制,比如樣例所給酋長的等級是 3 ,等級限制是 1,首先需要肯定你一定要跟酋長交易,所以樣例所給的等級限制是2~3 和 3~4兩種情況。附鏈接:http://poj.org/problem?id=1062

大體思路:這道題一旦理解清楚了,應該也能想到這是最短路問題(但題目一開始就很難理解)。因爲可以 1 號物品有幾種替代品,這裏可以想象成從 1 出發有幾條路可以到達某個結點 n,然後從 n 出發又有幾條路可以到達其它地方,最後求的是從 1 出發到達其它各點最短的是多遠。但題目有個限制就是等級,所以一開始可以將這些不滿足等級限制的結點標識成已訪問,這個問題就解決了。不過還有一個問題,就是怎麼分類?這個可以將所有情況枚舉,就樣例所給的,先枚舉等級 2~3 的情況,求出最短路後,再枚舉等級 3~4 的情況,再求出最短路,然後兩個最短路取最小輸出。

以下是ac代碼

#include<iostream>
#include<cstring>
using namespace std;

const int maxn=105;
const int inf=1e9;
int box[maxn][maxn];
int level[maxn];
int price[maxn];
int vis[maxn];
int n,m;

int dijkstra(int start){
    int dist[maxn];
    for(int i=1;i<=n;i++)  //這裏需要注意,初始化爲inf,不能爲box[1][i],就因爲這裏wa兩次,查了一個多小時
        dist[i]=inf;
    dist[1]=0;  //初始化爲0,以便第一次循環從1開始
    for(int i=0;i<n;i++){
        int Min=inf,k=-1;
        for(int j=1;j<=n;j++)
            if(!vis[j]&&dist[j]<Min){
                Min=dist[j];
                k=j;
            }
        if(k==-1)
            break;
        vis[k]=1;
        for(int j=1;j<=n;j++)
            if(!vis[j]&&dist[j]>dist[k]+box[k][j])
                dist[j]=dist[k]+box[k][j];
    }
    int Min=inf;
    for(int i=1;i<=n;i++)     //計算最短路時,記得加上原先的價格
        Min=min(Min,price[i]+dist[i]);
    return Min;
}
int main(){
    while(cin>>m>>n){
        int k;
        for(int i=0;i<=n;i++)
            for(int j=0;j<=n;j++)
                box[i][j]=inf;
        for(int i=1;i<=n;i++){
            cin>>price[i]>>level[i]>>k;
            for(int j=1;j<=k;j++){
                int a,b;
                cin>>a>>b;
                box[i][a]=b;
            }
        }
        int Min=inf;
        for(int i=0;i<=m;i++){   //枚舉等級,一開始還擔心超時。
            memset(vis,0,sizeof(vis));   //全部標識爲未訪問
            for(int j=1;j<=n;j++)
                if((level[1]-m+i)>level[j]||level[j]>(level[1]+i)) //等級之外標識爲已訪問
                    vis[j]=1;
            Min=min(Min,dijkstra(1));
        }
        cout<<Min<<endl;
    }
    return 0;
}


發佈了39 篇原創文章 · 獲贊 8 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章