思路:最短路+floyd
分析:
1 题目讲的是有一个湖100x100这个人刚开始在一个直径为15的圆心在原点的园内,然后要通过跳跃的方式问我们他是否能够到达岸边。如果可以求出最短的路径和步数
2 很明确就是最短路问题。但是这个时候问题来了,起点和终点是在哪里,所以我们采用的是将原点作为起点,岸边做为终点。知道了起点和终点,我们就可以求最短路,但是这个时候会碰到另外一个问题,边的长度。对于这个问题,我们是采取的方法是将这些点分成三类。1类:起点 2类:终点 3类:其它点 ,那么我们就可以分别对这三类的点求出它和其它点的距离。
注意事项:
1 输入的数据中,点的范围可能会在园内或在湖外,所以在输入的时候要判断点是否合法。
2 这一题精度要求很严格,一些比较之类的要注意精度问题
3 注意n = 0 的情况,这里如果n = 0,但是d > 42.5 是可以跳出去的。但是只要有乌龟,这个人就必须通过踩在乌龟上面跳出去,所以n = 0是比较特殊的。
4 n不大所以什么方法都可以做
5 求所需几步的时候利用一个setp[][]数组,首先初始户为0然后将可以到达的点标记为1,最后只要在更新dis[][]的时候更新即可。
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define MAXN 110
#define INF 0xFFFFFFF
#define eps 1e-12
int n;
double d;
double dis[MAXN][MAXN];
int setp[MAXN][MAXN];
struct Point{
int x;
int y;
}p[MAXN];
/*初始话边*/
void init(){
memset(setp , 0 , sizeof(setp));/*初始话为0*/
/*第三类的点*/
for(int i = 2 ; i < n ; i++){
for(int j = 2 ; j < n ; j++){
double tmp_x = (p[i].x-p[j].x)*(p[i].x-p[j].x);
double tmp_y = (p[i].y-p[j].y)*(p[i].y-p[j].y);
double tmp = sqrt(tmp_x + tmp_y);
if(tmp-d <= eps){
dis[i][j] = tmp;
setp[i][j] = 1;
}
else
dis[i][j] = INF;
}
dis[i][i] = 0;
}
/*第一类点*/
dis[1][1] = 0;
dis[1][n] = dis[n][1] = INF;
for(int i = 2 ; i < n ; i++){
double tmp = sqrt((p[i].x)*(p[i].x)*1.0+(p[i].y)*(p[i].y)*1.0);
if(tmp-7.5-d <= eps){/*注意要减去7.5*/
dis[1][i] = dis[i][1] = tmp-7.5;
setp[1][i] = setp[i][1] = 1;
}
else
dis[1][i] = dis[i][1] = INF;
}
/*第二类点*/
dis[n][n] = 0;
for(int i = 2 ; i < n ; i++){
int a = 50-abs(p[i].x);
int b = 50-abs(p[i].y);
int min = a < b ? a : b;
if(min-d <= eps){
dis[i][n] = dis[n][i] = min;
setp[i][n] = setp[n][i] = 1;
}
else
dis[i][n] = dis[n][i] = INF;
}
}
/*floyd算法*/
void floyd(){
for(int k = 1 ; k <= n ; k++){
for(int i = 1 ; i <= n ; i++){
for(int j = 1 ; j <= n ; j++){
if(dis[i][j]-(dis[i][k]+dis[k][j]) >= eps){
dis[i][j] = dis[i][k]+dis[k][j];
setp[i][j] = setp[i][k] + setp[k][j];/*更新数组*/
}
}
}
}
}
int main(){
int a , b , j;
while(scanf("%d %lf" , &n , &d) != EOF){
j = 2;/*默认1为起点,j从2开始*/
for(int i = 0 ; i < n ; i++){
scanf("%d%d" , &a , &b);
if(abs(a) < 8 && abs(b) < 8 || abs(a) > 50 && abs(b) > 50)/*如果不合法就跳过*/
continue;
p[j].x = a;
p[j++].y = b;
}
n = j;
if(!n){/*判断n是否为0*/
if(d-42.5 >= eps)
printf("42.50 1\n");
else
printf("can't be saved\n");
continue;
}
init();
floyd();
if(dis[1][n] != INF)/*是否可以跳出去*/
printf("%0.2lf %d\n" , dis[1][n] , setp[1][n]);
else
printf("can't be saved\n");
}
return 0;
}