首页 > 代码库 > HDU 5040 BFS+状压

HDU 5040 BFS+状压

2014 ACM/ICPC Asia Regional Beijing Online

对于N*N的矩阵

M起点,T终点

有起始方向分别向北N,东E,南S,西W的摄像头,可以检测的范围为自己+所指方向1格,每1秒顺时针旋转90°

前面有灯或者自己站的地方有灯,移动需要花3秒,或者原地等一秒。


BFS优先队列

开3维 hash数组判重,第三维是在该点等待的时间,开到4即可(摄像头转一圈)

对图中的每个点提前处理处会在什么时候被摄像头看到,用2进制压缩存储在MAP数组中

然后常规BFS解决

比赛时候手残没写CASE。。。。找了半天错误。。。。。

/*
                   _ooOoo_
                  o8888888o
                  88" . "88
                  (| -_- |)
                  O\  =  /O
               ____/`---'\____
             .'  \\|     |//  `.
            /  \\|||  :  |||//             /  _||||| -:- |||||-             |   | \\\  -  /// |   |
           | \_|  ''\---/''  |   |
           \  .-\__  `-`  ___/-. /
         ___`. .'  /--.--\  `. . __
      ."" '<  `.___\_<|>_/___.'  >'"".
     | | :  `- \`.;`\ _ /`;.`/ - ` : | |
     \  \ `-.   \_ __\ /__ _/   .-` /  /
======`-.____`-.___\_____/___.-`____.-'======
                   `=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         fozubaoyou    pass System Test!
*/
#include "stdio.h"
#include "string.h"
#include "queue"
using namespace std;
int inf=0x3f;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
struct node
{
    int x,y,step,wait; // step记录步数,wait记录等待的时间
    friend bool operator<(node n1,node n2)
    {
        return n1.step>n2.step;
    }
};
int s_x,s_y,n;
int b[5];
char str[510][510]; 
int map[510][510],hash[510][510][5]; // MAP 存储每个点什么时候会被看到,HASH判重第三维是在该点等待的时间

int bfs()
{
    priority_queue<node>q;
    node cur,next;
    int i,time;

    cur.x=s_x;
    cur.y=s_y;
    cur.step=0;
    cur.wait=0;
    q.push(cur);
    memset(hash,inf,sizeof(hash));
    hash[cur.x][cur.y][0]=0;

    while (!q.empty())
    {
        cur=q.top();
        q.pop();
        if (str[cur.x][cur.y]=='T') return cur.step;
        for (i=0;i<4;i++)
        {
            next.x=cur.x+dir[i][0];
            next.y=cur.y+dir[i][1];

            if (next.x<0 || next.x>=n || next.y<0 || next.y>=n) continue;
            if (str[next.x][next.y]=='#') continue;


            time=b[cur.step%4];
            if ((map[cur.x][cur.y]&time)==time || (map[next.x][next.y]&time)==time) // 当前点或下一个点会被看到
                next.step=cur.step+3;
            else
                next.step=cur.step+1;
            next.wait=0;
            if (next.step<hash[next.x][next.y][next.wait])
            {
                q.push(next);
                hash[next.x][next.y][next.wait]=next.step;
            }
        }

        next.x=cur.x;
        next.y=cur.y;
        next.step=cur.step+1;
        next.wait=cur.wait+1;

        if (next.wait<=3  && next.step<hash[next.x][next.y][next.wait]) // 原地等待
        {
            q.push(next);
            hash[next.x][next.y][next.wait]=next.step;
        }
    }
    return -1;

}

int main()
{
    int Case,ii,i,j;
    scanf("%d",&Case);
    b[0]=1; b[1]=2; b[2]=4; b[3]=8;
    for (ii=1;ii<=Case;ii++)
    {
        scanf("%d",&n);
        getchar();
        for (i=0;i<n;i++)
            gets(str[i]);
        printf("Case #%d: ",ii);

        memset(map,0,sizeof(map));
        for (i=0;i<n;i++) // 状压存储每个点什么时候会被看到
            for (j=0;j<n;j++)
            {
                if (str[i][j]=='M') { s_x=i; s_y=j;}
                if (str[i][j]=='N')
                {
                    map[i][j]=15;
                    if (i-1>=0) map[i-1][j]|=1;
                    if (j+1<n)  map[i][j+1]|=2;
                    if (i+1<n)  map[i+1][j]|=4;
                    if (j-1>=0) map[i][j-1]|=8;
                }
                if (str[i][j]=='E')
                {
                    map[i][j]=15;
                    if (j+1<n)  map[i][j+1]|=1;
                    if (i+1<n)  map[i+1][j]|=2;
                    if (j-1>=0) map[i][j-1]|=4;
                    if (i-1>=0) map[i-1][j]|=8;
                }
                if (str[i][j]=='S')
                {
                    map[i][j]=15;
                    if (i+1<n)  map[i+1][j]|=1;
                    if (j-1>=0) map[i][j-1]|=2;
                    if (i-1>=0) map[i-1][j]|=4;
                    if (j+1<n)  map[i][j+1]|=8;
                }
                if (str[i][j]=='W')
                {
                    map[i][j]=15;
                    if (j-1>=0) map[i][j-1]|=1;
                    if (i-1>=0) map[i-1][j]|=2;
                    if (j+1<n)  map[i][j+1]|=4;
                    if (i+1<n)  map[i+1][j]|=8;
                }
            }

        printf("%d\n",bfs());

    }
    return 0;
}




HDU 5040 BFS+状压