昂贵的聘礼(poj1062)dijkstra
#include <stdio.h>
int main()
{
//distance[i]表示i到已经到达的点的最小距离,origin[101][101]是图的邻接矩阵存储,M是等级限制,n为物品总数,图中共有n+1个点,rank[i]为第i个主人的等级
int M,n,i,j,k,jcost,origin_max=0,distance[101],min_cost,origin[101][101],rank[101],temp,last_rank,vertex,min_distance;
//flag[i]存放第i个节点是否已经到达
bool flag[101];
scanf("%d %d",&M,&n);
//邻接矩阵初始化
for(i=0;i<=n;i++)
for(j=0;j<=n;j++)
origin[i][j]=-1;
//对每个物品初始化
for(i=1;i<=n;i++)
{
scanf("%d %d %d",&origin[0][i],&rank[i],&temp);
//对每一个替代品,初始化origin
for(k=0;k<temp;k++)
{
scanf("%d %d",&j,&jcost);
origin[j][i]=jcost;
}
}
//取邻接矩阵中的最大值origin_max
for(i=0;i<=n;i++)
for(j=0;j<=n;j++)
if(origin[i][j]>origin_max)
origin_max=origin[i][j];
//如果没有值就设为origin_max+1,这样不会对结果有影响
for(i=0;i<=n;i++)
for(j=0;j<=n;j++)
if(origin[i][j]==-1)
origin[i][j]=origin_max+1;
min_cost=origin_max+1;
//last_rank表示酋长的rank
last_rank=rank[1];
//假如酋长的rank(last_rank)=10,等级限制M=5,那么可以参与交易的等级有以下6种可能:5-10 6-11 7-12 8-13 9-14 10-15
//下面这个循环就是分别处理这M+1种可能
for(i=0;i<=M;i++)
{
//这M+1种可能是独立的,一定不能相互影响,然后取最小值,所以要在副本上(copy[][])进行操作
//开始一直wa就是这里出了问题,找了很长时间
int copy[101][101];
for(j=0;j<=n;j++)
for(k=0;k<=n;k++)
copy[j][k]=origin[j][k];
//对每一个主人(除了酋长)的rank检查是否在要求的rank范围内,如果不在就将其代价设为最大值(origin_max+1)
for(j=2;j<=n;j++)
{
if(rank[j]<last_rank-M+i||rank[j]>last_rank+i)
for(k=0;k<=n;k++)
{
copy[j][k]=origin_max+1;
}
}
//下面是Dijkstra算法,和prim算法极为相似
//将flag设为false,除了flag[0]
for(j=0;j<=n;j++)
{
flag[j]=false;
distance[j]=copy[0][j];
}
flag[0]=true;
//循环直到终点出现在可到达的距离中
while(true)
{
min_distance=origin_max+1;
for(j=1;j<=n;j++)
{
//找到最小距离加入到集合中
if(!flag[j]&&distance[j]<min_distance)
{
vertex=j;
min_distance=distance[j];
}
}
//如果加入的是终点,即酋长
if(vertex==1)
{
//发现更小的距离
if(min_cost>min_distance)
min_cost=min_distance;
break;
}
flag[vertex]=true;
//更新最小距离
for(j=1;j<=n;j++)
{
if(!flag[j])
distance[j]=distance[j]<copy[vertex][j]+distance[vertex]?distance[j]:copy[vertex][j]+distance[vertex];
}
}
}
printf("%d\n",min_cost);
return 1;
}
int main()
{
//distance[i]表示i到已经到达的点的最小距离,origin[101][101]是图的邻接矩阵存储,M是等级限制,n为物品总数,图中共有n+1个点,rank[i]为第i个主人的等级
int M,n,i,j,k,jcost,origin_max=0,distance[101],min_cost,origin[101][101],rank[101],temp,last_rank,vertex,min_distance;
//flag[i]存放第i个节点是否已经到达
bool flag[101];
scanf("%d %d",&M,&n);
//邻接矩阵初始化
for(i=0;i<=n;i++)
for(j=0;j<=n;j++)
origin[i][j]=-1;
//对每个物品初始化
for(i=1;i<=n;i++)
{
scanf("%d %d %d",&origin[0][i],&rank[i],&temp);
//对每一个替代品,初始化origin
for(k=0;k<temp;k++)
{
scanf("%d %d",&j,&jcost);
origin[j][i]=jcost;
}
}
//取邻接矩阵中的最大值origin_max
for(i=0;i<=n;i++)
for(j=0;j<=n;j++)
if(origin[i][j]>origin_max)
origin_max=origin[i][j];
//如果没有值就设为origin_max+1,这样不会对结果有影响
for(i=0;i<=n;i++)
for(j=0;j<=n;j++)
if(origin[i][j]==-1)
origin[i][j]=origin_max+1;
min_cost=origin_max+1;
//last_rank表示酋长的rank
last_rank=rank[1];
//假如酋长的rank(last_rank)=10,等级限制M=5,那么可以参与交易的等级有以下6种可能:5-10 6-11 7-12 8-13 9-14 10-15
//下面这个循环就是分别处理这M+1种可能
for(i=0;i<=M;i++)
{
//这M+1种可能是独立的,一定不能相互影响,然后取最小值,所以要在副本上(copy[][])进行操作
//开始一直wa就是这里出了问题,找了很长时间
int copy[101][101];
for(j=0;j<=n;j++)
for(k=0;k<=n;k++)
copy[j][k]=origin[j][k];
//对每一个主人(除了酋长)的rank检查是否在要求的rank范围内,如果不在就将其代价设为最大值(origin_max+1)
for(j=2;j<=n;j++)
{
if(rank[j]<last_rank-M+i||rank[j]>last_rank+i)
for(k=0;k<=n;k++)
{
copy[j][k]=origin_max+1;
}
}
//下面是Dijkstra算法,和prim算法极为相似
//将flag设为false,除了flag[0]
for(j=0;j<=n;j++)
{
flag[j]=false;
distance[j]=copy[0][j];
}
flag[0]=true;
//循环直到终点出现在可到达的距离中
while(true)
{
min_distance=origin_max+1;
for(j=1;j<=n;j++)
{
//找到最小距离加入到集合中
if(!flag[j]&&distance[j]<min_distance)
{
vertex=j;
min_distance=distance[j];
}
}
//如果加入的是终点,即酋长
if(vertex==1)
{
//发现更小的距离
if(min_cost>min_distance)
min_cost=min_distance;
break;
}
flag[vertex]=true;
//更新最小距离
for(j=1;j<=n;j++)
{
if(!flag[j])
distance[j]=distance[j]<copy[vertex][j]+distance[vertex]?distance[j]:copy[vertex][j]+distance[vertex];
}
}
}
printf("%d\n",min_cost);
return 1;
}

浙公网安备 33010602011771号