题目描述:
和主人交换物品,物品可以由别人的物品+money来替代。人和人之间交换有等级限制。求怎么能用最少的钱得到和主人交换的那个物品。
转化为问题:(1)节点有自己的权值,边也有权值,若across一个节点,则总权值不用加入该节点的权值,即每条路径的权值 =across的边的权值 + 最后一个点的权值。(2)节点存在等级值,一条路径上的节点等级差不超过m。求从主人那个点出发,最少权值的路试哪一条。
解题思路:
定点出发,求最短路径,基本思想是贪心——迪杰斯特拉(每次选择最短的边)。这里将图存成三元组的序列。存路径长度数组D[j](存出发点到j的最短路径值),记录出发点到任意符合条件点的路径长,最后加上末尾节点的权值W[j]。贪心过程记录下路径上的等级值Level[j][2],其中[j][0]表示贪心到j点的时候路径上的最低等级,[j][1]指路径上最高等级。利用等级值来判断加入一个新点的时候,下一个节点上的贪心值是否改变(这个更新值为走上一节点的路径才可能达到)。
时间复杂度为 O(v2)
代码:
#include<stdio.h>
#include <stdlib.h>
#include <math.h>
#define N 101
#define Infinity 1000000000
typedef struct {
int l;
int cash;
int t;
int T[N][2];
}Deal;
int m,n;
Deal deal[N];
int D[N], final[N];
int record[N][2];
main()
{
int i,j;
int min;
int w,flag;
scanf("%d%d",&m, &n);
for(i=1;i<=n;i++)
{
scanf("%d",&deal[i].cash);
scanf("%d",&deal[i].l);
scanf("%d",&deal[i].t);
for(j=1;j<=deal[i].t;j++)
scanf("%d%d",&deal[i].T[j][0],&deal[i].T[j][1]);
}
for(i=1; i<=n;i++)
for(j=1;j<=deal[i].t;j++)
if(fabs(deal[i].l - deal[deal[i].T[j][0]].l) >m)
deal[i].T[j][1] =Infinity;
//initialize
for(i=1; i<=n;i++)
{
D[i] = Infinity;
final[i] = 0;
}
D[1] = 0;
record[1][0] =deal[1].l;
record[1][1] =deal[1].l;
final[1] = 1;
for(i=1;i<=deal[1].t;i++)
{
if(fabs(deal[deal[1].T[i][0]].l - deal[1].l) <=m)
{
if(deal[deal[1].T[i][0]].l > deal[1].l)
{
record[deal[1].T[i][0]][1] = deal[deal[1].T[i][0]].l;
record[deal[1].T[i][0]][0] = deal[1].l;
}
else if(deal[deal[1].T[i][0]].l < deal[1].l)
{
record[deal[1].T[i][0]][0] = deal[deal[1].T[i][0]].l;
record[deal[1].T[i][0]][1] = deal[1].l;
}
else
{
record[deal[1].T[i][0]][1] = deal[1].l;