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

题目链接:

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;
}




你可能感兴趣的:(poj-3897-Maze Stretching 二分+BFS+优先队列)