hdu 5040 Instrusive(堆优化+dij)

来源:互联网 发布:网络词兔叽是什么意思 编辑:程序博客网 时间:2024/05/16 13:00

题目链接

Instrusive

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


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
23M...N...T3M.. ###..T
 

Sample Output
Case #1: 5Case #2: -1
 

Source
2014 ACM/ICPC Asia Regional Beijing Online 

题意:给一个N*N的网格,要从M走到T,' . '表示空格,' # '表示墙,‘ N ’,‘ S ',’ W ‘,' E '表示摄像头以及它们的初始方向,每秒摄像头顺时针旋转90度,摄像头可以监视2个格子(分别是它本身所在的格子和它当前方向前面的一个格子),人可以从当前格子走到相邻的4个格子,假设他行动过程中没有被监视需要花1s,否则要花3秒。问人从M走到T的最短时间。


题解:容易想到用dp[ i ][ j ][ k ]表示人在点(i,j),花费的时间%4为k(0,1,2,3 )的状态下的最短时间。因为我们知道了K,就知道了所有摄像头现在的状态。我们可以把每个状态看成一个点,最后就是求最短路。但是点数500*500*4,为10^6,用spfa要超时。因为一个状态最多只能转移出5个状态,所以图的边数很少,是稀疏图,而且所有的边权都为正,我们可以用堆优化的dij来做。最后我们还可以加一个剪枝,T所在的点第一次出队时的值就是答案,可以直接返回,原因很显然。详情见代码:

#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<queue>#include<stack>#include<set>using namespace std;#define nn 510#define inff 0x3ffffffftypedef __int64 LL;int n;char tu[nn][nn];bool dai[nn][nn][5];int sx,sy;int dir[4][2]={-1,0,0,1,1,0,0,-1};struct node{    int x,y,zt;    int val;    friend bool operator<(node xx,node yy)    {        return xx.val>yy.val;    }}sta,tem;int dp[nn][nn][5];bool inque[nn][nn][5];priority_queue<node>que;bool check(int x,int y){    if(x<0||x>=n||y<0||y>=n)        return false;    if(tu[x][y]=='#')        return false;    return  true;}inline void gengxin(int x,int y,int zt,int val){    if(dp[x][y][zt]>val)    {        dp[x][y][zt]=val;       // if(!inque[x][y][zt])        {           // inque[x][y][zt]=true;            tem.x=x,tem.y=y,tem.zt=zt;            tem.val=val;            que.push(tem);        }    }}bool zhao(int x,int y,int zt){    if(tu[x][y]=='N')        return true;    if(tu[x][y]=='W')        return true;    if(tu[x][y]=='S')        return true;    if(tu[x][y]=='E')        return true;    int dx,dy,i,ix;    for(i=0;i<4;i++)    {        dx=x+dir[i][0],dy=y+dir[i][1];        if(check(dx,dy))        {            ix=-1;            if(tu[dx][dy]=='N')                ix=(0+zt)%4;            if(tu[dx][dy]=='E')                ix=(1+zt)%4;            if(tu[dx][dy]=='S')                ix=(2+zt)%4;            if(tu[dx][dy]=='W')                ix=(3+zt)%4;            if(ix==-1)                continue;            if(dx+dir[ix][0]==x&&dy+dir[ix][1]==y)                return true;        }    }    return false;}int ans;void solve(){    int i,j,k;    while(que.size())        que.pop();    for(i=0;i<n;i++)    {        for(j=0;j<n;j++)        {            for(k=0;k<4;k++)            {                dp[i][j][k]=inff;               // inque[i][j][k]=false;            }        }    }    dp[sx][sy][0]=0;    tem.x=sx,tem.y=sy,tem.zt=0;    tem.val=0;    que.push(tem);    int x,y,zt,fei;    int dx,dy,ix;    while(que.size())    {        sta=que.top();        que.pop();       // inque[sta.x][sta.y][sta.zt]=false;        if(tu[sta.x][sta.y]=='T')//剪枝        {            ans=min(ans,dp[sta.x][sta.y][sta.zt]);            return ;        }        if(sta.val>dp[sta.x][sta.y][sta.zt])            continue;        x=sta.x,y=sta.y,zt=sta.zt;        fei=dp[sta.x][sta.y][sta.zt];        //gengxin(x,y,(zt+1)%4,fei+1);        for(i=0;i<4;i++)        {            dx=sta.x+dir[i][0],dy=sta.y+dir[i][1];            if(check(dx,dy))            {                ix=1;                if(dai[dx][dy][zt]||dai[sta.x][sta.y][zt])                {                    ix=3;                    if(dp[x][y][(zt+1)%4]>fei+1)//原地不动                    {                        dp[x][y][(zt+1)%4]=fei+1;                        tem.x=x,tem.y=y,tem.zt=(zt+1)%4;                        tem.val=fei+1;                        que.push(tem);                    }                }                //gengxin(dx,dy,(zt+ix)%4,fei+ix);                if(dp[dx][dy][(zt+ix)%4]>fei+ix)//到下一个点                {                    dp[dx][dy][(zt+ix)%4]=fei+ix;                    tem.x=dx,tem.y=dy,tem.zt=(zt+ix)%4;                    tem.val=fei+ix;                    que.push(tem);                }            }        }    }}int main(){    int t,i,j,k;    int cas=1;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        for(i=0;i<n;i++)        {            scanf("%s",tu[i]);            for(j=0;j<n;j++)            {                if(tu[i][j]=='M')                {                    sx=i,sy=j;                }            }        }        for(i=0;i<n;i++)//预处理每个点被摄像头监视的状态        {            for(j=0;j<n;j++)            {                for(k=0;k<4;k++)                {                    dai[i][j][k]=zhao(i,j,k);                }            }        }        ans=inff;        solve();        printf("Case #%d: ",cas++);        if(ans==inff)            puts("-1");        else            printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击