题目连接: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; }