题目链接:
http://poj.org/problem?id=3897
题目意思:
求竖直伸缩比例,使得从起点到终点的距离最小值恰好等于给定值。
未伸缩前水平和竖直的步长都为1。
解题思路:
二分伸缩比例,用BFS求在该竖直长度下的最短距离,直到该距离等于给定值。
搜索的时候,用优先队列来确定搜索位置,使得每次搜索都是从距离开始点的最短距离开始往后搜
代码:
#include<iostream> #include<cmath> #include<cstdio> #include<cstdlib> #include<string> #include<cstring> #include<algorithm> #include<vector> #include<map> #include<set> #include<stack> #include<list> #include<queue> #define eps 1e-8 #define INF 0x1f1f1f1f #define PI acos(-1.0) #define ll __int64 #define lson l,m,(rt<<1) #define rson m+1,r,(rt<<1)|1 using namespace std; /* freopen("data.in","r",stdin); freopen("data.out","w",stdout); */ char save[120][120]; double dis[120][120]; bool flag[120][120]; double sd; int dir[4][2]={-1,0,0,1,1,0,0,-1}; int n,m; struct Point { int x,y; }ss,ee; struct Inf { double len; Point p; friend bool operator <(Inf a,Inf b) //是优先队列中对头为最小的距离 { return a.len>b.len; } }; priority_queue<Inf>myp; bool iscan(Point xx) { if(xx.x<0||xx.x>n||xx.y<0||xx.y>m) return false; return true; } bool equal(Point a,Point b) { if(a.x==b.x&&a.y==b.y) return true; return false; } double BFS(double yy) //每次搜索都是从距离开始点的最短距离开始往后搜 { //myp.clear(); while(!myp.empty()) myp.pop(); Inf s; s.p=ss,s.len=0; myp.push(s); memset(flag,false,sizeof(flag)); flag[(s.p).x][(s.p).y]=1; while(!myp.empty()) { Inf ff=myp.top(); //表示到达该位置的最短距离 myp.pop(); for(int i=0;i<4;i++) { Point pp; pp.x=(ff.p).x+dir[i][0],pp.y=(ff.p).y+dir[i][1]; if(!iscan(pp)) continue; if(flag[pp.x][pp.y]) continue; if(save[pp.x][pp.y]!=' ') continue; Inf tmp=ff; tmp.p=pp; tmp.len=tmp.len+((i&1)?1:yy); if(equal(ee,pp)) //找到了最短距离 return tmp.len; flag[pp.x][pp.y]=1; myp.push(tmp); } } } int main() { int t; scanf("%d",&t); for(int ca=1;ca<=t;ca++) { scanf("%lf%d",&sd,&n); getchar(); for(int i=1;i<=n;i++) { gets(save[i]+1); //printf("%s\n",save[i]+1); for(int j=1;save[i][j];j++) { if(save[i][j]=='S') { ss.x=i,ss.y=j; save[i][j]=' '; //把起点和终点 置为可访问状态 } else if(save[i][j]=='E') { ee.x=i,ee.y=j; save[i][j]=' '; } } } //printf("%d %d %d %d\n",ss.x,ss.y,ee.x,ee.y); m=strlen(save[1]+1); //printf("%d %d\n",n,m); double l=0,r=1000,mid,ans; while(fabs(r-l)>eps) { mid=(l+r)/2; double tt=BFS(mid); //printf("%lf\n",tt); if(sd-tt>eps) //小了,往上放 { ans=mid; l=mid; } else r=mid; //大了,不行往下收 } printf("Case #%d: %0.3lf%%\n",ca,ans*100); } return 0; }