题目描述:
和主人交换物品,物品可以由别人的物品+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;
record[deal[1].T[i][0]][0] = deal[1].l;
}
}
D[deal[1].T[i][0]] = deal[1].T[i][1];
}
w = 1;
for(i=2; i<=n; i++)
{
min = Infinity;
flag = 0;
for(j=2; j<=n; j++)
if(!final[j])
{
if(D[j] < min)
{
w = j;
min = D[j];
flag = 1;
}
}
if(flag == 0)
continue;
final[w] = 1;
for(j=1; j<= deal[w].t; j++)
{
if(!final[deal[w].T[j][0]])
{
if(min+deal[w].T[j][1] < D[deal[w].T[j][0]])
{
if((fabs(deal[deal[w].T[j][0]].l-record[w][0]) <= m) &&(fabs(deal[deal[w].T[j][0]].l - record[w][1]) <= m))
{
if(deal[deal[w].T[j][0]].l > record[w][1])
{
record[deal[w].T[j][0]][1] = deal[deal[w].T[j][0]].l;
record[deal[w].T[j][0]][0] = record[w][0];
}
else if(deal[deal[w].T[j][0]].l < record[w][0])
{
record[deal[w].T[j][0]][0] = deal[deal[w].T[j][0]].l;
record[deal[w].T[j][0]][1] = record[w][1];
}
else
{
record[deal[w].T[j][0]][0] = record[w][0];
record[deal[w].T[j][0]][1] = record[w][1];
}
D[deal[w].T[j][0]] = min+deal[w].T[j][1];
}
}
}
}
}
min = Infinity;
for(i=1; i<=n; i++)
{
if(fabs(deal[i].l - deal[1].l) > m)
D[i] = Infinity;
else
D[i] += deal[i].cash;
if(D[i] < min)
min = D[i];
}
printf("%d\n",min);
//system("pause");
return 0;
}