hdu5040

       
       

Instrusive

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 1564    Accepted Submission(s): 465

Problem Description
The legendary mercenary Solid Matt gets a classic mission: infiltrate a military base. The military base can be seen as an N * N grid. Matt's target is in one of the grids and Matt is now in another grid. In normal case, Matt can move from a grid to one of the four neighbor grids in a second. But this mission is not easy. Around the military base there are fences, Matt can't get out of the base. There are some grids filled with obstacles and Matt can't move into these grids. There are also some surveillance cameras in the grids. Every camera is facing one of the four direction at first, but for every second, they will rotate 90 degree clockwisely. Every camera's sight range is 2, which means that if Matt is in the same grid as the camera, or in the grid that the camera is facing, he will be seen immediately and the mission will fail. Matt has a special equipment to sneak: a cardbox. Matt can hide himself in the card box and move without being noticed. But In this situation, Matt will have to use 3 seconds to move 1 grid. Matt can also just hide in the cardbox without moving. The time to hide and the time to get out of the cardbox can be ignored. Matt can't take the risk of being noticed, so he can't move without cardbox into a grid which is now insight of cameras or from a grid which is now insight of cameras. What's more, Matt may be in the cardbox at the beginning. As a live legend, Matt wants to complete the mission in the shortest time.
 

Input
The first line of the input contains an integer T, denoting the number of testcases. Then T test cases follow. For each test cases, the first line contains one integer:N(1<=N<=500) In the following N lines, each line contains N characters, indicating the grids. There will be the following characters: ● '.' for empty  ● '#' for obstacle  ● 'N' for camera facing north  ● 'W' for camera facing west  ● 'S' for camera facing south  ● 'E' for camera facing east  ● 'T' for target  ● 'M' for Matt
 

Output
For each test case, output one line "Case #x: y", where x is the case number (starting from 1) and y is the answer. If Matt cannot complete the mission, output '-1'.
 

Sample Input
          
          
2 3 M.. .N. ..T 3 M.. ### ..T
 
题意:一个n*n的矩阵,#表示墙,M表示人Matt,T表示目标,M要到T点去,#不可以走,路途有摄像头,如果被摄像头发现任务就是败了,摄像头可以看到两个格子的区域,一是自身所在区域,二是它面对方向的位子,摄像头可以转动,1秒转动一次,有四个方向N,S,W,E,表示 上北,下南,作西,右东,Matt有一个神秘盒子,他可以躲到里面不让摄像头发现,在盒子中移动每一格要花费3秒,不带盒子每移动一格花费1秒,也可以在盒子待着不动;问Matt到达T花费最短时间是多少,如果不能完成任务输出-1;
解决:bfs搜索+优先队列,用一个三维数组表示状态,刚开始我用了二维的,结果TLE,看了一下别人做的,发现用三维数组去记录状态更合适,因为一个位子有四种状态,也就是四个时间点,(所有摄像头都转,每4秒一个周期啊),也就是Matt最多在一个位子呆4秒,进行bfs时,要走的下一点位置要考虑4种情况:1 有摄像头,2被摄像头照射,3空地且不被摄像头照射,4是# 墙不可以通过; 策略:遇到情况1,要走,时间加3,第二种情况,要停等待一秒,时间加1位置不变,情况3,走,时间加1 ,情况4可以直接跳过不操作;
对于摄像头转向问题,用时间%4就可以计算出当前摄像头方向了;
我最开始用map<string ,int>M(映射),将四个方向与1~4联系起来的,也没有特意考虑映射关系(特殊考虑的话更巧妙),后来学习了别人用法没直接开一个int数组,[110],初始化为-1,然后用W,E,S,N的ASCII作为下标,然后赋值也是相当方便的;
考虑四个方向赋问题,可以结合搜索顺序,使得搜索顺序与方向代表值一一对应,举一个例子,我第一次向下S搜索,那么我要让‘N'赋值为0,也就是当搜索顺序值与方向值相等时刚好该位置被摄像图照射;
TLE代码:
#include <iostream>
#include <map>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <functional>

using namespace std;
int dx[4]= {1,0,-1,0};
int dy[4]= {0,1,0,-1};
const int maxn=510,maxm=400040;
const int inf=0x3f3f3f3f;
char str[maxn][maxn];
bool vis[maxn][maxn];
int time_[maxn][maxn];
int n;
int ti,tj;
map<char,int>M;
map<int,char>P;
void init()
{
    M['N']=1;
    M['E']=2;
    M['S']=3;
    M['W']=4;
}
int min(int a,int b)
{
    if(a<b)
        return a;
    return b;
}
struct point
{
    int x,y,t;
    friend bool operator< (const point &T1,const point &T2)
    {
        return T1.t>T2.t;
    }

};
bool check(int x,int y,int t)
{
    t=t%4;
    int nx,ny;
    for(int i=0;i<4;i++)
    {
        nx=dx[i]+x;
        ny=dy[i]+y;
        if(nx>=0&&nx<n&&ny>=0&&ny<n)
        {
            if(str[nx][ny]>='A'&&str[nx][ny]<='Z')
            {
                int temp=M[str[nx][ny]];
                temp+=t;
                if(temp>4)
                temp%=4;
                if(i==0&&temp==1)
                return false;
                if(i==1&&temp==4)
                    return false;
                if(i==2&&temp==3)
                    return false;
                if(i==3&&temp==2)
                    return false;
            }
        }

    }
    return true;
}
int bfs(point head)
{
    priority_queue<point>que;
    que.push(head);
    int ans=inf;
    int stop=0;
    while(!que.empty())
    {
        point next;
        point now=que.top();
        if(now.x==ti&&now.y==tj)
            return now.t;
        que.pop();
        int nx,ny;
        for(int i=0; i<4; i++)
        {
            nx=dx[i]+now.x;
            ny=dy[i]+now.y;
            if(str[nx][ny]=='#')
                continue;
            if(nx>=0&&nx<n&&ny>=0&&ny<n&&!vis[nx][ny])
            {
                if(str[nx][ny]=='.')
                {
                    if(check(nx,ny,now.t))
                    {
                        vis[nx][ny]=true;
                        next.x=nx;
                        next.y=ny;
                        next.t=now.t+1;
                        que.push(next);

                    }
                    else
                    {
                        next.x=now.x;
                        next.y=now.y;
                        next.t=now.t+2;
                        que.push(next);
                    }
                }
                if(str[nx][ny]<='Z'&&str[nx][ny]>='A')
                {
                    vis[nx][ny]=true;
                    next.x=nx;
                    next.y=ny;
                    next.t=now.t=3;
                    que.push(next);
                }
            }

        }
    }
    return ans;
}
int main()
{
    int t;
    int T=0;
    int mi,mj;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=0; i<n; i++)
        {
           scanf("%s",str[i]);
            for(int j=0; j<n; j++)
            {
                time_[i][j]=inf;
                if(str[i][j]=='M')
                    mi=i,mj=j;
                if(str[i][j]=='T')
                {
                       ti=i,tj=j;
                       str[i][j]='.';
                }

            }
        }
        point h;
        h.x=mi;
        h.y=mj;
        h.t=1;
        memset(vis,false,sizeof(vis));
        vis[h.x][h.y]=true;
       // time_[h.x][h.y]=0;
        int ans=bfs(h);
        printf("Case #%d: ",++T);
        if(ans==inf)
            printf("-1\n");
        else
            printf("%d\n",ans);

    }
    return 0;
}
 
    如果加以考虑全面,这个题还是挺简单的
AC代码:
#include <iostream>
#include <map>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <functional>

using namespace std;
int dx[4]= {0,-1,0,1};
int dy[4]= {-1,0,1,0};
const int maxn=510;
char str[maxn][maxn];
bool vis[maxn][maxn][5];
int n;
int change[maxn];
struct point
{
    int x,y,t;
    point()
    {
        ;
    }
    point(int nx,int ny,int nt)
    {
        x=nx;
        y=ny;
        t=nt;
    }
   bool operator<(const point s)const{return t>s.t;}

};
int  check(int x,int y,int t)
{
    if(x<0||x>=n||y<0||y>=n||str[x][y]=='#')
        return 0;///不操作
    if(change[str[x][y]]!=-1)
        return 1;///有摄像头或者被照射
    int nx,ny;
    int nowt;
    for(int i=0; i<4; i++)
    {
        nx=dx[i]+x;
        ny=dy[i]+y;
        if(nx<0||nx>=n||ny<0||ny>=n||str[nx][ny]=='#')
            continue;
        int temp=change[str[nx][ny]];
        if(temp>=0&&(temp+t)%4==i)
            return 1;

    }
    return 2;///通行无阻
}

int bfs(int fx,int fy)
{
    priority_queue<point>que;///优先队列
    memset(vis,false,sizeof(vis));
    que.push(point(fx,fy,0));

    while(!que.empty())
    {
        point now=que.top();
        que.pop();
    /// cout<<now.x<<" "<<now.y<<" "<<now.t<<endl;
        if(str[now.x][now.y]=='T')
            return now.t;
        int nx,ny,nowt;
        nowt=now.t+1;

        if(!vis[now.x][now.y][nowt%4])///考虑当前状态,未有过,加入队列
        {
            vis[now.x][now.y][nowt%4]=true;
            que.push(point(now.x,now.y,nowt));
        }
        int nowv=check(now.x,now.y,now.t);///检查当前状态
        for(int i=0; i<4; i++)
        {

            nx=dx[i]+now.x;
            ny=dy[i]+now.y;
            int sta=check(nx,ny,now.t);
            if(sta==0)
                continue;
            if(sta==1||nowv==1)///当前状态被照射或者下一位置被照射
                nowt=now.t+3;
            else if(sta==2)
                nowt=now.t+1;
            if(!vis[nx][ny][nowt%4])///判断该位置该时刻状态是否有过
            {
                vis[nx][ny][nowt%4]=true;
                que.push(point(nx,ny,nowt));
            }

        }
    }
    return -1;
}
int main()
{
    int t;
    int T=0;
    int mi,mj;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        memset(change,-1,sizeof(change));
        change['E']=0,change['S']=1,change['W']=2,change['N']=3;
        for(int i=0; i<n; i++)
        {
            scanf("%s",str[i]);
            for(int j=0; j<n; j++)
            {
                if(str[i][j]=='M')
                    mi=i,mj=j;
            }
        }
        int ans=bfs(mi,mj);
        printf("Case #%d: %d\n",++T,ans);
    }
    return 0;
}






  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值