MinTime

实验任务
众所周知,索隆是一个路痴,一天在一小岛上,他又迷路了!!好基友山治心急如焚,
决定出去找他,由于练成了月步,山治的速度竟然达到了正无穷!小岛上除了空地,还有盘
丝洞(简称 psd) , 盘丝洞里住着可爱的妹纸,山治每次经过一个盘丝洞,都要停留一个单
位时间来欣赏妹纸,给你一个 n*m 的地图以及山治和索隆当前位置,山治想请你帮他算算他
最快要多久才能见到索隆。
数据输入
输入第一行为两个正整数 n,m (2 <=n,m <=1000), 表示有 n m 列,最左上角的坐标为
1,1)。
接下来 n 行,每行 m 个字符, “ .” 代表盘丝洞,“ X”代表空地,只有‘ .’和’X’两种字
符,山治通过盘丝洞需 1 个单位时间,通过空地无需花费时间。
最后两行分别表示山治和索隆的当前坐标。 (你可以假设这两个坐标都在空地上,即
X’)。
数据输出
对于每个询问,输出一行一个整数,表示山治最快见到索隆的时间。
输入示例   输出示例
6 6           3
..X...
XXX.X.
....X.
X.....
X.....

X.X...

 #include<iostream>   
using namespace std;  
struct MinTime  
{  
      long int x,y;  
      long int mintime,add;   
      MinTime()  
      {  
          mintime=1998;   
          add=0;  
      }  
};    
void buildheap(MinTime**head,MinTime*p,long int son,long int father,long int sail)  
{  
    bool ok=1;   
    while(ok&&son<=sail)  
     {  
         if(son<sail&&head[son]->mintime>head[son+1]->mintime)son++;  
         if(p->mintime>head[son]->mintime)  
         {  
             head[father]=head[son];  
             father=son;  
             son*=2;  
         }  
         else   
             ok=0;   
     }  
     head[father]=p;   
}  
long int push(MinTime**head,MinTime*p, long int min, long int sail)  
{     
     long int father,son;  
     bool ok=1;  
     if(head[1]->add>3)  
     {  
         buildheap(head,p,2,1,sail);   
     }  
     else  
     {  
        sail++;  
        son=sail;  
        father=son/2;  
        while(ok&&father>0)  
        {  
          if(head[father]->mintime>p->mintime)  
          {  
             head[son]=head[father];  
             son=father;  
             father/=2;  
          }  
          else ok=0;  
           
        }     
        buildheap(head,p,son*2,son,sail);  
     }  
     while(head[1]->add>3)  
     {  
         buildheap(head,head[sail],2,1,sail-1);  
         sail--;   
     }  
 return sail;  
}   
long int runtime(MinTime**MT,long int n,long int m,char**c)  
{  
    long int xx,yy,x,y,a,b,max,sail,next[4][2]={-1,0,1,0,0,-1,0,1};  
    bool ok;  
    scanf("%d%d%d%d",&x,&y,&a,&b);   
    max=x>a?x-a:a-x;   
    max+=y>b?y-b:b-y;   
    x--;y--;a--;b--;  
    MinTime**head;   
    head=new MinTime*[n*m];  
    head[1]=&MT[x][y];  
    MT[x][y].mintime=0;    
    MT[x][y].x=x;  
    MT[x][y].y=y;   
    MT[a][b].mintime=max;  
    ok=1;  
    sail=1;   
    while(ok)  
    {      
           xx=head[1]->x+next[head[1]->add][0];  
           yy=head[1]->y+next[head[1]->add][1];   
           head[1]->add++;  
           if(xx>=0&&xx<n&&yy>=0&&yy<m)  
           {  
              if(c[xx][yy]=='.')max=head[1]->mintime+1;  
              else max=head[1]->mintime;   
              if(MT[xx][yy].mintime>max)  
              {  
                   MT[xx][yy].mintime=max;  
                  if(MT[xx][yy].mintime<MT[a][b].mintime)  
                  {  
                   MT[xx][yy].x=xx;  
                   MT[xx][yy].y=yy;   
                   sail=push(head,&MT[xx][yy],MT[a][b].mintime,sail);  
                  }   
                  else if(MT[head[1]->x][head[1]->y].mintime>=MT[a][b].mintime)  
                      ok=0;  
              }  
           }   
        if(head[1]->add>3)  
        {  
            buildheap(head,head[sail],2,1,sail-1);  
            sail--;  
        }  
    }        
    if(c[a][b]=='.')MT[a][b].mintime--;  
    return MT[a][b].mintime;   
}  
int main()  
{  
    long int n,m,add;  
    char **sign;  
    MinTime**MT;  
    scanf("%d%d",&n,&m);   
    MT=new MinTime*[n];  
    for(add=0;add<n;add++)  
        MT[add]=new MinTime [m];  
    sign=new char*[n];    
    for(add=0;add<n;add++)  
        sign[add]=new char [m+1];  
    for(add=0;add<n;add++)  
    {  
       scanf("%s",sign[add]);  
    }   
    n=runtime(MT,n,m,sign);  
    printf("%d\n",n);   
    for(add=0;add<n;add++)  
        delete MT[add];  
    delete MT;  
    return 0;  
}  



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值