1. 程式人生 > >POJ 1062 昂貴的聘禮(最短路中等題)

POJ 1062 昂貴的聘禮(最短路中等題)

clu inf fin 遍歷 () 交易 超過 給他 main

昂貴的聘禮
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 51879 Accepted: 15584

Description

年輕的探險家來到了一個印第安部落裏。在那裏他和酋長的女兒相愛了,於是便向酋長去求親。酋長要他用10000個金幣作為聘禮才答應把女兒嫁給他。探險家拿不出這麽多金幣,便請求酋長降低要求。酋長說:"嗯,如果你能夠替我弄到大祭司的皮襖,我可以只要8000金幣。如果你能夠弄來他的水晶球,那麽只要5000金幣就行了。"探險家就跑到大祭司那裏,向他要求皮襖或水晶球,大祭司要他用金幣來換,或者替他弄來其他的東西,他可以降低價格。探險家於是又跑到其他地方,其他人也提出了類似的要求,或者直接用金幣換,或者找到其他東西就可以降低價格。不過探險家沒必要用多樣東西去換一樣東西,因為不會得到更低的價格。探險家現在很需要你的幫忙,讓他用最少的金幣娶到自己的心上人。另外他要告訴你的是,在這個部落裏,等級觀念十分森嚴。地位差距超過一定限制的兩個人之間不會進行任何形式的直接接觸,包括交易。他是一個外來人,所以可以不受這些限制。但是如果他和某個地位較低的人進行了交易,地位較高的的人不會再和他交易,他們認為這樣等於是間接接觸,反過來也一樣。因此你需要在考慮所有的情況以後給他提供一個最好的方案。
為了方便起見,我們把所有的物品從1開始進行編號,酋長的允諾也看作一個物品,並且編號總是1。每個物品都有對應的價格P,主人的地位等級L,以及一系列的替代品Ti和該替代品所對應的"優惠"Vi。如果兩人地位等級差距超過了M,就不能"間接交易"。你必須根據這些數據來計算出探險家最少需要多少金幣才能娶到酋長的女兒。

Input

輸入第一行是兩個整數M,N(1 <= N <= 100),依次表示地位等級差距限制和物品的總數。接下來按照編號從小到大依次給出了N個物品的描述。每個物品的描述開頭是三個非負整數P、L、X(X < N),依次表示該物品的價格、主人的地位等級和替代品總數。接下來X行每行包括兩個整數T和V,分別表示替代品的編號和"優惠價格"。

Output

輸出最少需要的金幣數。

Sample Input

1 4
10000 3 2
2 8000
3 5000
1000 2 1
4 200
3000 2 1
4 200
50 2 0

Sample Output

5250

思路:
一開始的思路是以酋長為起點,直接求他到每個符合要求的點的最長的路徑,然後遍歷一遍所有點,找出優惠最大的就好了,後面發現實際寫的時候很麻煩,處理起來有點麻煩。
實際這道題因為不管怎麽換最後都要和酋長換,所以應該以酋長為終點,然後直接枚舉所有符合題目要求的點到酋長的最短路徑然後找出這些路徑裏面最小的就行了。

實現代碼:
#include<iostream>
#include<cstdio>
#include
<cstring> using namespace std; #define INF 0x3f3f3f3f #define M 200 int price[M],rank[M],n,g[M][M],cnt,dist[M],vis[M],u,m,id,num; void init(){ memset(price,0,sizeof(price));memset(rank,0,sizeof(rank)); for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) g[i][j] = INF; } void dij(){ for(int i=1;i<=n;i++) dist[i] = price[i]; int n1 = n; while(n1--){ int minn = INF; for(int i=1;i<=n;i++) if(dist[i]<minn&&!vis[i]) dist[u=i]; vis[u] = 1; for(int i=1;i<=n;i++){ if(!vis[i]&&dist[i]>dist[u]+g[u][i]) dist[i] = dist[u] + g[u][i]; } } } int main(){ while(scanf("%d%d",&cnt,&n)!=EOF){ init(); for(int i=1;i<=n;i++){ scanf("%d%d%d",&price[i],&rank[i],&m); for(int j=1;j<=m;j++){ scanf("%d%d",&id,&num); g[id][i] = num; } } int ans = INF; for(int i=1;i<=n;i++){ int max_rank = rank[i]; for(int j=1;j<=n;j++){ if(rank[j]<max_rank||rank[j]-max_rank>cnt) vis[j] = 1; else vis[j]=0; } dij(); ans = min(ans,dist[1]); } cout<<ans<<endl; } return 0; }

POJ 1062 昂貴的聘禮(最短路中等題)