hdu 5040(2014年北京赛区网络赛)

题意:M是起点,T是终点,‘.'是路,‘#’是墙,中间有很多摄像头都有初始的方向,而且每隔一秒钟要顺时针转90度,被照到的时候有两种选择,可以原地不动,也可以用三秒走一个格子,问你从起点到终点的最短时间,如果不能到达输出-1.


思路:如果当前点和要走的点都是通路,如果被照到了,那就原地不动或者是在盒子里面走(要用三秒),这样我们可以知道我们最多在原地等三秒,要不就不是最优的了,如果前面是灯就只有花三秒走过去了,这道题要注意的是不能用普通的状态来保存,因为走过的点不一定就是最优的,所以我们要另外开一个二维数组来保存当前位置最短的时间,这样来标记状态,还有就是要用优先队列,因为走一个格子的时间不是相同的。


AC代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=510;
const int inf=1<<29;
int xx[4]={0,0,-1,1},yy[4]={-1,1,0,0};
int n,t,mx,my,tx,ty;
char Map[maxn][maxn];
int d[maxn][maxn];
struct node
{
    int x;
    int y;
    int step;
    bool operator<(const node &p) const
    {
        return step>p.step;
    }
}m,nxt;
int check(int x,int y)
{
    if(x<0||y<0||x>=n||y>=n)
        return 1;
    return 0;
}
int lpf(int x,int y,int time)
{
    if(Map[x][y]!='.')
        return 0;
    if(x-1>=0)
    {
        if(time==0&&Map[x-1][y]=='S')
            return 0;
        else if(time==1&&Map[x-1][y]=='E')
            return 0;
        else if(time==2&&Map[x-1][y]=='N')
            return 0;
        else if(time==3&&Map[x-1][y]=='W')
            return 0;
    }
    if(x+1<n)
    {
        if(time==0&&Map[x+1][y]=='N')
            return 0;
        else if(time==1&&Map[x+1][y]=='W')
            return 0;
        else if(time==2&&Map[x+1][y]=='S')
            return 0;
        else if(time==3&&Map[x+1][y]=='E')
            return 0;
    }
    if(y-1>=0)
    {
        if(time==0&&Map[x][y-1]=='E')
            return 0;
        else if(time==1&&Map[x][y-1]=='N')
            return 0;
        else if(time==2&&Map[x][y-1]=='W')
            return 0;
        else if(time==3&&Map[x][y-1]=='S')
            return 0;
    }
    if(y+1<n)
    {
        if(time==0&&Map[x][y+1]=='W')
            return 0;
        else if(time==1&&Map[x][y+1]=='S')
            return 0;
        else if(time==2&&Map[x][y+1]=='E')
            return 0;
        else if(time==3&&Map[x][y+1]=='N')
            return 0;
    }
    return 1;
}
int bfs()
{
    for(int i=0;i<=n;i++)
        for(int j=0;j<=n;j++)
        d[i][j]=inf;
    priority_queue<node> q;
    q.push(m);
    d[m.x][m.y]=0;
    while(!q.empty())
    {
        m=q.top();
        q.pop();
        if(m.x==tx&&m.y==ty)
            return m.step;
        for(int i=0;i<4;i++)
        {
            nxt.x=m.x+xx[i];
            nxt.y=m.y+yy[i];
            nxt.step=m.step+1;
            if(check(nxt.x,nxt.y))
                continue;
            if(Map[nxt.x][nxt.y]=='#')
                continue;
            if(Map[nxt.x][nxt.y]=='.')
            {
                int flag=0;
                for(int j=0;j<3;j++)      //最多等三秒
                {
                    int time=(m.step+j)%4;
                    if(lpf(m.x,m.y,time)&&lpf(nxt.x,nxt.y,time)&&nxt.step+j<d[nxt.x][nxt.y])    //如果两个点都没被照到
                    {
                        nxt.step+=j;
                        d[nxt.x][nxt.y]=nxt.step;
                        q.push(nxt);
                        flag=1;
                        break;
                    }
                }
                if(!flag)
                {
                    nxt.step+=2;
                    if(nxt.step<d[nxt.x][nxt.y])
                    {
                        d[nxt.x][nxt.y]=nxt.step;
                        q.push(nxt);
                    }
                }
            }
            else
            {
                nxt.step+=2;
                if(nxt.step<d[nxt.x][nxt.y])
                {
                    d[nxt.x][nxt.y]=nxt.step;
                    q.push(nxt);
                }
            }
        }
    }
    return -1;
}
int main()
{
    scanf("%d",&t);
    for(int k=1;k<=t;k++)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%s",Map[i]);
            for(int j=0;j<n;j++)
            {
                if(Map[i][j]=='M')
                {
                    m.x=i;
                    m.y=j;
                    m.step=0;
                    Map[i][j]='.';
                }
                else if(Map[i][j]=='T')
                {
                    tx=i;
                    ty=j;
                    Map[i][j]='.';
                }
            }
        }
        printf("Case #%d: %d\n",k,bfs());
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值