题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1245
题意:给一个已知直径的圆形岛,然后岛的附近是湖,湖里有一些点,以坐标的形式给出,最外层是矩形的终点。
给定跳跃的距离d,让你判断是否能跳到最外层,如果能就输出最短距离以及这个最短跳的步数。
题解:
这题重点在建图,在松弛操作那里也要修改一下。详细看代码。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<algorithm>
#include<functional>
#define cl(a,b) memset(a,b,sizeof(a));
#define FFC(i,a,b) for(int i=a;i<=b;i++)
#define FFI(i,a,b) for(int i=a;i>=b;i--)
#define pb push_back
#define LL long long
using namespace std;
void fre(){freopen("c:\\acm\\input.txt","r",stdin);}
const double INF=1e9,eps=1e-5;
const int MAXN=110,MAXM=11000;
typedef pair<double,int>P;
priority_queue<P,vector<P>,greater<P> >Q;
int v[MAXM],g[MAXN],nxt[MAXM],ed,i,x,N,pre[MAXN];
double w[MAXM],d[MAXN];
int n,xx,yy,cnt,K;
void init(int n){for(i=1,ed=0,N=n;i<=n;i++)g[i]=0;}
void adg(int x,int y,double z){v[++ed]=y,w[ed]=z,nxt[ed]=g[x],g[x]=ed;}
void dijkstra(int S){
for(i=1;i<=N;i++)d[i]=INF,pre[i]=S;Q.push(P(d[S]=0,S));
while(!Q.empty()){
P t=Q.top();Q.pop();
if(t.first>d[x=t.second])continue;
for(i=g[x];i;i=nxt[i])if(d[x]+w[i]<d[v[i]]&&!(w[i]>K)){//距离必须小于K才能跳
pre[v[i]]=x;//记录路径
Q.push(P(d[v[i]]=d[x]+w[i],v[i]));
}
}
}
struct dt{
int x,y;
}a[110];
int abs(int a){return a<eps?-a:a;}
double getdis(int a,int b,int c,int d){return sqrt(1.0*(a-c)*(a-c)+(b-d)*(b-d));}
void build_g(){
//以1为起点
FFC(i,2,cnt){
double tmp=getdis(0,0,a[i].x,a[i].y);
if(tmp<=7.5){adg(1,i,0);adg(i,1,0);}
else if(tmp-7.5-K<=eps&&tmp-7.5>eps){adg(1,i,tmp-7.5);adg(i,1,tmp-7.5);}
}
FFC(i,2,cnt)FFC(j,i,cnt){
if(i==j){adg(i,j,0);adg(j,i,0);}
else{
double tmp=getdis(a[i].x,a[i].y,a[j].x,a[j].y);
adg(i,j,tmp);
adg(j,i,tmp);
}
}
//cnt+1为终点
FFC(i,2,cnt){
int min=(50-abs(a[i].x))>(50-abs(a[i].y))?(50-abs(a[i].y)):(50-abs(a[i].x));
adg(cnt+1,i,(double)min);
adg(i,cnt+1,(double)min);
}
}
int getlong(){
int an=0,i=cnt+1;
while(pre[i]!=i){
i=pre[i],an++;
}
return an;
}
int main(){
//fre();
while(~scanf("%d%d",&n,&K)){
cnt=1;
FFC(i,1,n){
scanf("%d%d",&xx,&yy);
if(xx<50&&yy<50)a[++cnt].x=xx,a[cnt].y=yy;
}
//特判,如果K大于42.5可一步跳到岸边
if(K>=42.5){printf("42.50 1\n");continue;}
init(cnt+1);
build_g();//建图
dijkstra(1);
double ans=d[cnt+1];
if(ans<INF)printf("%.2lf %d\n",ans,getlong());
else printf("can't be saved\n");
}
return 0;
}