poj1062 2010.3.5
Poj 1062昂贵的聘礼
【关键字】
最短路
【摘要】
探险家想获得某样物品,可以直接买,花费P;也可以获得另外一种物品,再加上V金币来换取。
另外,与探险家交换的人都有个级别。他只能在一个长度为M + 1的下界不定的范围的级别的人内交换。举个例子,M为1,他要是与级别为3的人交换了,就不能与级别为1的人交换了,反之亦然。
求出,探险家想获取物品0所需花费的最少金币数。
【正文】
1、题目描述
昂贵的聘礼
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 12652 Accepted: 3318
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
输出最少需要的金币数。
SampleInput
1 4
10000 3 2
2 8000
3 5000
1000 2 1
4 200
3000 2 1
4 200
50 2 0
SampleOutput
5250
Source
浙江
2、算法分析
先把每个物品放在一个数组goods里,标记每个物品的price和rank。顺便把每个rank存在另一个数组ranklist里。并把ranklist排序,从大到小或者从小到大无所谓。增加一个物品节点,rank跟酋长的一样,使他到每个节点都有一条路,路的权是那些节点本身的price。其他节点间如果可以交换就也建条路。如此,图就建成了。然后枚举每个不相同的rank,作为最高等级,每次用dijkstra前,把那些等级比他高的还有跟它差距大于M的节点通通去掉。然后就是经典的dijkstra,从goods[gonum+1]走到goods[1] ,即从自己加的那个节点到酋长节点。不用任何其他修改。返回sum,就是那条最短路径。最后找出最短路径中的最小值。
如果 rank[i] 与酋长的rank的差值的绝对值大于标准的话,则,不考虑该条路~~~这个就是等级的限定条件了
3、源码
#include <stdio.h>
#include <string.h>
#include <math.h>
#define INF 1000000000
#define N 100+10
int map[N][N],rank[N];
int high[N],low[N];
int n,mm;
int min(int,int);
int max(int,int);
void init()
{
int i,j,t,k,val;
memset(map,0,sizeof(map));
scanf("%d %d",&mm,&n);
for(i=1;i<=n;i++)
{
scanf("%d %d %d",&map[0][i],&rank[i],&t);
high[i]=rank[i];
low[i]=rank[i];
for(j=1;j<=t;j++)
{
scanf("%d %d",&k,&val);
map[k][i]=val;
}
}
}
void dijkstra()
{
int d[N],v[N];
int i,j;
memset(v,0,sizeof(v));
d[0]=0;
for (i=1;i<=n;i++)
if ((map[0][i])&&(abs(rank[1]-rank[i])<=mm))d[i]=map[0][i];
else d[i]=INF;
for (i=1;i<=n;i++)
{
int x,m=INF,y;
for(y=1;y<=n;y++)
if ((!v[y]) && (d[y]<m)) m=d[x=y];
v[x]=1;
for(y=1;y<=n;y++)
{
if ((map[x][y])&&(abs(rank[1]-high[y])<=mm)&&(abs(rank[1]-low[y])<=mm)&&(d[y]>d[x]+map[x][y]))
{
high[y]=max(rank[x],high[y]);
low[y]=min(rank[x],low[y]);
d[y]=d[x]+map[x][y];
}
}
}
printf("%d\n",d[1]);
}
int main()
{
init();
dijkstra();
return 0;
}
int max(int a,int b)
{
if (a>b) return a;
else return b;
}
int min(int a,int b)
{
if (a>b) return b;
else return a;
}