题意:有很多石头,青蛙一在一号石头上,求它跳到二号石头,求一个路线,使得这个路线中最大的一次跳跃最小。
题解:这种最大的最小的绕口令题用二分很多都可以做,以最短的边为底,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,有没有连在一起,因为边按照从小到大排序,所以这条边就是这个路线中最大的,直接返回这个边的值就可以了。