https://vjudge.net/contest/375481#problem/B
这也是一道dijkstra算法的变形
这道题主要就是存边的时候需要用到结构体数组 存每个具体点的信息 然后才能两两遍历 存两条线段间的长度
初始化dist[1]很必要 因为dist是double型的 值不再是最大值 是一个很小的值(0.000476792)
(int 情况下memset dist 最大值后 自动会更新点1的出边值)
总体思路:1.存边
2.确定更新后的最小值点(题意是要在所有必要跳跃线段中最小的线)
3.更新点 max函数的使用原理 :向下个线段更新需要选择下与下一个点相比更大的点 (这才称为每个线段的必要跳跃距离)
min函数的使用原理 :原来的线看做是一条路 现在的线是一条路 相当于做一次二选一 与环节2确定更新点意义有点像 选择较小的那条路(最小必要跳跃距离)
4.输出 dist[2]
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int N=210,M=1100;
double g[M][M];
double dist[N];
int n;
bool st[N];
int ans=1;
struct edge{
int x,y;
}edges[M];//用结构体把编号为i的点映射到具体值
double distance(int tx,int ty)
{
return sqrt((double)(edges[tx].x-edges[ty].x)*(edges[tx].x-edges[ty].x)+(edges[tx].y-edges[ty].y)*(edges[tx].y-edges[ty].y));
}
double dijkstra()
{
memset(dist,0x3f,sizeof dist);
dist[1]=0;
//for(int i=1;i<=n;i++)
//{
// cout<<dist[i]<<endl;
//}
for(int i=1;i<=n;i++)
{
dist[i]=g[1][i]; // 初始化dist[i] 但是我个人觉得没有必要 memset dist出现了问题
}
for(int i=0;i<n;i++)
{
int t=-1;
for(int j=1;j<=n;j++)
{
if(!st[j] &&(t==-1 || dist[j]<dist[t])) //找到更新后的点中的最小值 因为每次都要选必要线段中的最小值
{
t=j;
}
}
st[t]=true;
for(int j=1;j<=n;j++)
{
dist[j]=min(dist[j],max(dist[t],g[t][j]));
//相当于两条路做二选一 t是一个新插足的点 min里的d[j]是之前存在的
//dist[j]代表是j前的一小段,dist[j]
}
}
return dist[2];
}
int main()
{
while(cin>>n)
{
if(n==0) break;
else {
memset(st,0,sizeof st);
memset(g,0x3f,sizeof g);
for(int i=1;i<=n;i++)
{
cin>>edges[i].x>>edges[i].y; //给结构体数组输入点
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
g[i][j]=g[j][i]=distance(i,j);// 用结构体 将i,j映射到具体点上
}
}
double u=dijkstra();
cout<<"Scenario #"<<ans++<<endl;
cout<<"Frog Distance = ";
printf("%.3f\n",u);
cout<<endl;
}
}
return 0;
}