poj 1062_最短路径

来源:互联网 发布:java通过ip获取地区 编辑:程序博客网 时间:2024/06/05 02:22

题目描述:

 和主人交换物品,物品可以由别人的物品+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;
}

原创粉丝点击