POJ 1062

//POJ 1062 昂贵的聘礼
//思路:枚举、Dijkstra算法
#include <iostream>
using namespace std;
typedef struct
{
 int id;
 int price;
}tidai;
typedef struct
{
 int price;
 int position;
 int tidai_num;
 //用于存贮每种货物的替代品
 tidai *tidais;
}good;
//定义动态二维数组
typedef int* IntArrayPtr;
int main()
{

 int position_gap,num;
 while(cin>>position_gap>>num)
 {
  //用于存储货物
  good *goods = new good[num+1];
  IntArrayPtr *cell = new IntArrayPtr[num+1];
  //定义动态二维数组
  for(int u = 0;u<num+1;u++)
  {
   cell[u] = new int[num+1];
  }
  int *d = new int[num+1];
  int *position = new int[num+1];
  bool *final = new bool[num+1];

  for(int o=1;o<num+1;o++)
  {
   for(int z=1;z<num+1;z++)
   {
    cell[o][z] = -1;
   }
  }

  for(int l=1;l<num+1;l++)
  {
   cin>>goods[l].price>>goods[l].position>>goods[l].tidai_num;
      goods[l].tidais = new tidai[goods[l].tidai_num];
   cell[l][l] = goods[l].price;
   for(int s=0;s<goods[l].tidai_num;s++) //tidais的下标从0开始
   {
    cin>>goods[l].tidais[s].id>>goods[l].tidais[s].price;
   }
  }  

  for(int f=1;f<num+1;f++)
  {
   for(int r=0;r<goods[f].tidai_num;r++)
   {
    cell[f][goods[f].tidais[r].id] = goods[f].tidais[r].price;
   }
  }
  int origin_max = 0;
  //求取输入数据中的最大值,用于设置距离之间的无穷小
  for(int v=1;v<num+1;v++)
  {
   for(int w=1;w<num+1;w++)
   {
    if(cell[v][w]>origin_max)
    {
     origin_max = cell[v][w];
    }
   }
  }
  for(int aa=1;aa<num+1;aa++)
  {
   for(int bb=1;bb<num+1;bb++)
   {
    //如果两点之间的距离没有设置,则将两点之间距离设置为origin_max+1
    if(cell[aa][bb]==-1)
    {
     cell[aa][bb] = origin_max+1;
    }
   }
  }

  int qu_position = goods[1].position;
  IntArrayPtr *copy = new IntArrayPtr[num+1];
  for(int z = 0;z<num+1;z++)
  {
   copy[z] = new int[num+1];
  }
  
  //枚举:假如酋长的rank(last_rank)=10,等级限制M=5,那么可以参与交易的等级有以下6种可能:5-10 6-11 7-12 8-13 9-14 10-15
  //下面这个循环就是分别处理这M+1种可能,其中M数组中存储的是每次循环中的最短距离
  int *M = new int[position_gap+1];
  for(int w=0;w<position_gap+1;w++)
  { 
   M[w] = cell[1][1];
   //这M+1种可能是独立的,一定不能相互影响,然后取最小值,所以要在副本上(copy[][])进行操作
   for(int c=1;c<num+1;c++)
   {
    for(int v=1;v<num+1;v++)
    {
     copy[c][v] = cell[c][v];
     //cout<<copy[c][v]<<" ";
    }
    //cout<<endl;
   }
           
   for(int f=2;f<num+1;f++)
   {
    //对每一个主人(除了酋长)的rank检查是否在要求的rank范围内,如果不在就将其代价设为最大值(origin_max+1)
    if((goods[f].position<qu_position-position_gap+w)|| (goods[f].position>qu_position+w))
    {
     for(int r=1;r<num+1;r++)
     {
      copy[r][f] =  origin_max+1;
      copy[f][r] =  origin_max+1;
     }
    }
   }
            //Dijsktra求最短路径
   for(int q=1;q<num+1;q++)
   {
    d[q] = copy[1][q];
    final[q] = false;
   }
   int n =1;
   final[1] = true;
   for(int p =2;p<num;p++)
   {
    int min = origin_max+1;
    for(int m=2;m<num+1;m++)
    {
     if(!final[m])
      if(d[m]<min)
      {
       min = d[m];
       n = m;
      }
    }
    final[n] = true;
    for(int a = 2;a<num+1;a++)
    {
     if(!final[a])
     {
      if(d[n]+copy[n][a]<d[a])
      {
       d[a] = d[n] + copy[n][a];
      }
     }   
    }
   }
   //求出到每个点的最短路径后,再加上自身的环,求出最小值。注:Dijkstra算法无法处理环
   for(int cc = 2;cc<num+1;cc++)
   {
    d[cc] += copy[cc][cc];
    if(d[cc] < M[w])
     M[w] = d[cc];
   }
  }  
  int min_price = origin_max+1;
  for(int t=0;t<position_gap+1;t++)
  {
   if(M[t]<min_price)
    min_price = M[t];
  }
  cout<<min_price<<endl;

  //二维动态数组的销毁
  for(int y = 0;y<num+1;y++)
  {
   delete []cell[y];
   delete []copy[y];
   if(y!=0)
   {
    delete []goods[y].tidais;
   }
  }
  delete []cell;
  delete []d;
  delete []position;
  delete []final;
  delete []goods;
  delete []copy;
  delete []M;
 } 
 return 0;
}

posted @ 2010-03-24 22:27  北海小龙  阅读(502)  评论(0编辑  收藏  举报