其他分享
首页 > 其他分享> > POJ-2253 Frogger

POJ-2253 Frogger

作者:互联网

题目:https://vjudge.net/problem/POJ-2253

这题先是要看懂题目,题目的大致意思就是给你n个点的坐标,其中第一个点是起点,第二个点是终点,从起点到终点肯定有很多条路径,而每一条路径中又有许多小线段组成(两个点之间的线段),让你求所有路径中最长线段的最小值。

这题可以分别用最短路径算法和最小生成树来做

1:这里我用的是dijkstra算法,先看代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath> 
using namespace std;
const int maxn = 250;
const int INF = 0x3f3f3f3f;
double e[maxn][maxn],dis[maxn];
int x[maxn],y[maxn],n;
bool vis[maxn];
void solve(){
	for(int i = 1; i <= n; i++) dis[i] = e[1][i];
	vis[1] = true;
	for(int k = 1; k <= n-1; k++){
		int pos;
		double minn = INF;
		for(int i = 1; i <= n; i++){
			if(vis[i] == false && dis[i] < minn){
				pos = i;
				minn = dis[i];
			}
		}
		vis[pos] = true;
		for(int i = 1; i <= n; i++){
			dis[i] = min(dis[i],max(dis[pos],e[pos][i])); // mark
		}
	}
}
int main()
{
	//freopen("in.txt","r",stdin);
	int num = 1;
	while(1){
		scanf("%d",&n);
		if(n == 0) break;
		memset(vis,false,sizeof(vis));
		for(int i = 1; i <= n; i++){
			scanf("%d%d",&x[i],&y[i]);
		}
		for(int i = 1; i <= n; i++){
			for(int j = i+1; j <= n; j++){
				e[i][j] = e[j][i] = sqrt(double(x[i]-x[j])*(x[i]-x[j])+double(y[i]-y[j])*(y[i]-y[j]));
			}
			e[i][i] = 0;
		}
		solve();
		printf("Scenario #%d\nFrog Distance = %.3lf\n\n",num++,dis[2]);
	}
	return 0;
 } 

可以看到和dijkstra模板不一样的只是代码中我标记的那一句,这里的dis[i] 表示1号点到i号点所有路径中最长线段的最小值。我们想想要求得1号点到2号的所有路径中最长线段的最小值,除了本身1号点和2号点直接相连的距离外,肯定有某些点使得从1号点经过这些点最后到达2号点的这条路径的最长线段更优,这样就很像‘松弛’操作了,那问题又来了,怎么选中间点呢?选离1号点最近的点进行松弛操作,因为1号点到这个点本身就是一条路径,并且还是最短的,那就不存在其他点使得1号点通过其他点到达这个点的结果更优,就以这种策略不断松弛下去,最后的dis[2] 就是答案

2:最小生成树:看题解的时候看到了这种方法,正好写写复习一下相关知识点

我们将每两个点之间的距离从小到大进行排序,如果在加入某个边后使得1,2号点联通了,那么这条边就是答案,仔细想想其实很好理解,我们是从小到大进行加边的,在加入某条边后使得1,2号点联通了,那么这条边肯定在1到2的路径上,又因为是从小到大进行加边的,所以这条边一定是所有路径中最长边的最小值

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 250;
int n,x[maxn],y[maxn],f[maxn];
struct Node
{
	int x;
	int y;
	double dis;
}node[maxn*maxn];
bool cmp(Node x,Node y){
	return x.dis < y.dis;
}
void init(){
	for(int i = 1; i <= n; i++) f[i] = i;
}
int getf(int x){
	if(f[x] == x) return x;
	else{
		f[x] = getf(f[x]);
		return f[x];
	}
}

void merge(int x,int y){
	int fx,fy;
	fx = getf(x);fy = getf(y);
	if(fx != fy) f[fy] = fx;
}
int main()
{
	//freopen("in.txt","r",stdin);
	int num = 1;
	while(~scanf("%d",&n) && n){
		for(int i = 1; i <= n; i++){
			scanf("%d%d",&x[i],&y[i]);
		}
		int cnt = 0;
		for(int i = 1; i <= n; i++){
			for(int j = i+1; j <= n; j++){
				node[++cnt].x = i;
				node[cnt].y = j;
				node[cnt].dis = sqrt(double(x[i]-x[j])*(x[i]-x[j])+double(y[i]-y[j])*(y[i]-y[j]));
			}
		}
		sort(node+1,node+cnt+1,cmp);
		double ans;
		init();
		for(int i = 1; i <= cnt; i++){
			ans = node[i].dis;
			merge(node[i].x,node[i].y);
			if(getf(1) == getf(2)) break;
			//cout<<ans<<endl;
		}
		printf("Scenario #%d\nFrog Distance = %.3lf\n\n",num++,ans);
	}
	return 0;
 } 

标签:int,dis,路径,POJ,maxn,include,2253,号点,Frogger
来源: https://www.cnblogs.com/Beic233/p/12885182.html