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;
}