poj-3897-Maze Stretching 二分+BFS+优先队列

来源:互联网 发布:2017淘宝图片尺寸要求 编辑:程序博客网 时间:2024/05/22 17:29

题目链接:

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)|1using 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;}