链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1245
题目:
4 10 17 0 27 0 37 0 45 0 1 10 20 30
42.50 5 can't be saved
分析与总结:
本题建图是关键:
1. 把整个这个岛看作为点0,由于中间的岛的直径为15,那么每只鳄鱼能否从岛上跳上需要特判,如果某只鳄鱼如果距离中心点(0,0)为dis,那么只要dis-7.5<=d, 就可以建立这条边的关系
2. 把整个岸边看为点n+1, 由于每只鳄鱼距离岸上的距离也不同,所以也需要特判。 取每只鳄鱼距离四个岸边最短的那个距离为权值。求距离岸边的方法: 我们知道湖的范围为(i,j),-50<i=j<50, 对于鳄鱼坐标(x,y), 50-max(abs(x), abs(y))便是这个坐标距离岸边最短的距离。
3. 本题很难发现的Trick:
(1) 对于每只鳄鱼的坐标,有可能是不合法的,可能会是在中间的岛上,也能是在岸上,所以需要先过滤判断。
(2) 如果James Bond可以跳的距离d大于42.50(岛到岸边的距离),那么可以直接跳到岸上,步数为1
建好图之后,用最短路算法计算即可。
另外,由于还要计算步数,再增加一个权值step,都赋值为1即可
代码:
用Dijkstra
#include<cstdio> #include<cstring> #include<math.h> #include<iostream> using namespace std; typedef double Type; const int VN = 205; const int INF=0x7fffffff/2; int n,size; double D; double x[VN]; double y[VN]; Type d[VN]; Type w[VN][VN]; int s[VN][VN]; int step[VN]; bool vis[VN]; int pos; int end[VN]; double getDist(int i, int j){ return sqrt(pow(x[i]-x[j],2)+pow(y[i]-y[j],2)); } void init(){ pos = 0; size=0; x[0] = y[0] = 0; } double bankDist(double i, double j){ //增加岸边上的点 return 50*1.0-max(fabs(i), fabs(j)); } void Dijkstra(int src){ memset(vis, 0, sizeof(vis)); for(int i=0; i<=n; ++i) d[i]=INF,step[i]=INF; step[src] = d[src] = 0; for(int i=0; i<=n; ++i){ int u=-1; for(int j=0; j<=n; ++j)if(!vis[j]){ if(u==-1 || d[j]<d[u]) u=j; } vis[u] = 1; for(int j=0; j<=n; ++j)if(!vis[j]){ Type tmp = d[u]+w[u][j]; int tmp_s = step[u]+s[u][j]; if(d[j]>tmp){ d[j]=tmp; step[j]=tmp_s; } else if(d[j]==tmp&&step[j]>tmp_s) step[j]=tmp_s; } } } int main(){ double a,b; while(~scanf("%d%lf",&n,&D)){ if(D>=42.5){ puts("42.50 1"); continue; } init(); for(int i=1; i<=n; ++i){ scanf("%lf%lf",&a,&b); if(fabs(a)<=7.5&&fabs(b)<=7.5 || fabs(a)>50 || fabs(b)>50)continue; x[++size]=a, y[size]=b; } n = size+1; for(int i=0; i<=n; ++i){ w[i][i] = INF; s[i][i] = 0; for(int j=i+1; j<=n; ++j){ w[i][j]=w[j][i]=INF; s[i][j]=s[j][i]=1; } } for(int i=1; i<=size; ++i){ double dis = getDist(0,i); if(dis-7.5<=D){ // 从小岛可以跳上的点,整个小岛为点0 w[0][i] = w[i][0] = dis-7.5; } // 从该点能否跳到岸上 dis = bankDist(x[i],y[i]); if(dis<=D){ w[i][n]=w[n][i]=dis; } for(int j=i+1; j<=size; ++j){ dis = getDist(i,j); if(dis<=D){ w[i][j] = w[j][i] = dis; } } } Dijkstra(0); if(d[n]!=INF)printf("%.2f %d\n",d[n],step[n]); else puts("can't be saved"); } return 0; }
—— 生命的意义,在于赋予它意义。
原创 http://blog.csdn.net/shuangde800 , By D_Double (转载请标明)