題幹:
年輕的探險家來到了一個印第安部落裏。在那裏他和酋長的女兒相愛了,於是便向酋長去求親。酋長要他用10000個金幣作爲聘禮才答應把女兒嫁給他。探險家拿不出這麼多金幣,便請求酋長降低要求。酋長說:"嗯,如果你能夠替我弄到大祭司的皮襖,我可以只要8000金幣。如果你能夠弄來他的水晶球,那麼只要5000金幣就行了。"探險家就跑到大祭司那裏,向他要求皮襖或水晶球,大祭司要他用金幣來換,或者替他弄來其他的東西,他可以降低價格。探險家於是又跑到其他地方,其他人也提出了類似的要求,或者直接用金幣換,或者找到其他東西就可以降低價格。不過探險家沒必要用多樣東西去換一樣東西,因爲不會得到更低的價格。探險家現在很需要你的幫忙,讓他用最少的金幣娶到自己的心上人。另外他要告訴你的是,在這個部落裏,等級觀念十分森嚴。地位差距超過一定限制的兩個人之間不會進行任何形式的直接接觸,包括交易。他是一個外來人,所以可以不受這些限制。但是如果他和某個地位較低的人進行了交易,地位較高的的人不會再和他交易,他們認爲這樣等於是間接接觸,反過來也一樣。因此你需要在考慮所有的情況以後給他提供一個最好的方案。
爲了方便起見,我們把所有的物品從1開始進行編號,酋長的允諾也看作一個物品,並且編號總是1。每個物品都有對應的價格P,主人的地位等級L,以及一系列的替代品Ti和該替代品所對應的"優惠"Vi。如果兩人地位等級差距超過了M,就不能"間接交易"。你必須根據這些數據來計算出探險家最少需要多少金幣才能娶到酋長的女兒。
思路:
(物品原價,主人級別)這個二元組作爲一個節點
節點與節點之間根據替代品相連接(有向連接),連接的權值是出度節點物品優惠後的價格
現在就是要找路徑,從(酋長女兒,酋長),到每個節點,路徑長度規定爲每段路徑的權值加上終節點的物品原價。並且要求,
每條路徑中任意兩個節點的主人級別差不超過M(通過維護當前路徑中主任級別的最大值和最小值)
把上面的路徑做以下修訂: 增加一個匯點X,X連接每一個節點,並且權值爲每一個節點中的物品原價。
這樣,題目就變爲找出原點到匯點X的最短路徑(並且要求,每條路徑中任意兩個節點的主人級別差不超過M)
源代碼:
#include<stdio.h>
#include<stdlib.h>
struct adjacent{
int weight;
int maxLevel;
int minLevel;
};
int goods[20][3];//goods[][0]存放原價 goods[][1]存放主人Level goods[][2]存放代替品數量 ,匯點level規定和酋長一樣
int dijstra( struct adjacent arr[20][20], int M, int num ){//源點是0
int min,i,k,time;
//假設num-1號是匯點
//初始化源點到其餘各點的路徑中主人level的最大值和最小值
for( i=1; i<num; ++i ){
arr[0][i].maxLevel = goods[i][1] > goods[0][1] ? goods[i][1] : goods[0][1];
arr[0][i].minLevel = goods[i][1] > goods[0][1] ? goods[0][1] : goods[i][1];
}
for( time = 1; time < num; ++time ){
for( min = 9999999,i=1,k=0; i<num; ++i ){//尋找源點到其他所有點距離的最短值
if( arr[0][i].weight < min ){
min = arr[0][i].weight;
k = i;//記錄下最短值的節點
}
}
printf("%d,%d\n",min,k);system("pause");
for( i=1; i<num; ++i ){//用這個最短值修訂其他 (要考慮路徑的最大級別差M)
if( arr[0][k].weight + arr[k][i].weight < arr[0][i].weight ){
if( goods[i][1] >= arr[0][k].minLevel && goods[i][1] <= arr[0][k].maxLevel ){
arr[0][i].weight = arr[0][k].weight + arr[k][i].weight;
} else{
if( abs( goods[i][1]-arr[0][k].minLevel )<=M && abs( goods[i][1]-arr[0][k].maxLevel )<=M ){
arr[0][i].weight = arr[0][k].weight + arr[k][i].weight;
if( goods[i][1] < arr[0][k].minLevel )
arr[0][k].minLevel = goods[i][1];
if( goods[i][1] > arr[0][k].maxLevel )
arr[0][k].maxLevel = goods[i][1];
}
}
}
}
if( k == num-1 )
return arr[0][num-1].weight;
arr[0][k].weight = 9999999;
}
}
int main(){
int i, j, M, num, n, discount,result;
struct adjacent arr[20][20];
scanf("%d %d",&M,&num);
for( i=0; i<num; ++i ){
for( j=0; j<num; ++j ){
arr[i][j].weight = 9999999;
}
}//初始化鄰接數組
for( i=0; i<num; ++i ){
scanf("%d %d %d",&goods[i][0],&goods[i][1],&goods[i][2]);
for( j=0; j<goods[i][2]; ++j ){
scanf("%d %d",&n, &discount);
arr[i][n-1].weight = discount;
}
}//建立鄰接矩陣
for( i=0; i<num; ++i ){
arr[i][num].weight = goods[i][0];
}//向原圖中添加匯點
goods[num][1] = goods[0][1];
++num;
result = dijstra( arr, M, num );
printf("%d",result);
system("pause");
}