POJ 2253 Frogger dijkstra 二分 最小生成树

题目

题意:有很多石头,青蛙一在一号石头上,求它跳到二号石头,求一个路线,使得这个路线中最大的一次跳跃最小。

题解:这种最大的最小的绕口令题用二分很多都可以做,以最短的边为底,1,2的距离为顶,进行二分,检查的时候搜索一遍,看能不能在每次跳跃都小于mid的情况下找到2。

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include <algorithm>
using namespace std;
int n;
struct node{
    double x,y;
}a[205];
double dis(node a,node b){
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int vis[205];
double mp[205][205];
int bfs(double x){
    memset(vis,0,sizeof(vis));
    queue<int >que;
    que.push(1);
    vis[1]=1;
    int i,temp;
    while(!que.empty()){
        temp=que.front();
        vis[temp]=1;
        if(temp==2)return 1;
        que.pop();
        for(i=1;i<=n;i++){
            if(mp[temp][i]<=x&&!vis[i]){
                que.push(i);
            }
        }
    }
    return 0;
}
int main(){
    int i,j,icase=0;
    double minn=6000000;
    while(scanf("%d",&n)){
        minn=6000000;
        if(n==0)break;
        for(i=1;i<=n;i++)scanf("%lf%lf",&a[i].x,&a[i].y);
        for(i=1;i<=n;i++){
            for(j=1;j<i;j++){
                    mp[i][j]=mp[j][i]=dis(a[i],a[j]);
                    if(mp[i][j]<minn)minn=mp[i][j];
            }
        }
        double st=minn,en=mp[1][2];
        double mid;
        mid=(st+en)/2.0;
        while(en-st>1e-5){
            mid=(st+en)/2.0;
            if(bfs(mid))en=mid;
            else st=mid;
        }
        if(icase)printf("\n");
	printf("Scenario #%d\nFrog Distance = %.3f\n",++icase,st);
    }
    return 0;
}

PS:应该是精度问题,G++过不了;

也可以看成是最短路的变形,dis[x]表示从x到1的最长跳跃的最大值。更新就取dis[x]和mp[x][i]中的最大,和当前的dis[i]比出来最小。

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include <algorithm>
#define INF 600000
using namespace std;
int n;
struct node{
    double x,y;
}a[205];
double idis(node a,node b){
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int vis[205];
double mp[205][205],dis[205];
void dijkstra(){
	int i,j;
	memset(vis, 0, sizeof(vis));
	for(i=1; i<=n; i++) dis[i] = (i==1) ? 0 : INF;
	for( i=1; i<=n; i++){
        int x,m = INF;
        for(j=1; j<=n; j++)
            if(!vis[j] && dis[j] <= m){
            x = j;
            m = dis[x];
        }
        vis[x] = 1;
        for(j=1; j<=n ;j++) dis[j] = min(dis[j], max(dis[x], mp[x][j]));
    }
}
int main(){
    int i,j,icase=0;
    while(scanf("%d",&n)){
        if(n==0)break;
        for(i=1;i<=n;i++)scanf("%lf%lf",&a[i].x,&a[i].y);
        for(i=1;i<=n;i++){
            for(j=1;j<i;j++){
                    mp[i][j]=mp[j][i]=idis(a[i],a[j]);
            }
        }
        dijkstra();
        if(icase)printf("\n");
        printf("Scenario #%d\nFrog Distance = %.3f\n",++icase,dis[2]);
    }


    return 0;}
//还可以用最小生成树,用k算法添加一条边的时候检查1,2,有没有连在一起,因为边按照从小到大排序,所以这条边就是这个路线中最大的,直接返回这个边的值就可以了。

猜你喜欢

转载自blog.csdn.net/nwpu2017300135/article/details/80628566