[BFS]C

Problem C: C

Time Limit: 5 Sec   Memory Limit: 128 MB
Submit: 36   Solved: 5
[ Submit][ Status][ Web Board]

Description

X opened his eyes slowly and found himself in a strange place. He remembered that he was kidnaped by alien last night. He looked around, relized that he was at a rectangular mountaintop which is a matrix of N * M, and surround by cliffs.
X must be very careful otherwise he might fell off the cliffs. There are many stone walls on the mountaintop. X also found a note in his pocket, says "Your cellphone is at somewhere on the mountop, find it and call your friend Mario for help!". X was able to move one space at four directions (up, down, left, right) every second, of course he can't move on a stone wall. X had 3 bananas in his bag, and he could stand on an banana-peel to slide towards a direction until he hit the wall or fall off the cliffs in one second. Every banana-peel can only be used only one time.
 Suddenly, X remembered he had learnt the skill of jumping-over-wall from Y. He could jump over one or some consecutive stone walls in one of the four directions(Of course he can't stand on a stone wall).
 It takes 1 second for one jump, he can jump only when he beside the wall and he can't jump over a grid which there isn't a wall. Every one unit of wall costs him 1 energy to jump. He eat 3 bananas, so he have 3 energy initially.
 X want to return to his dormitory to play LOL as soon as possible, can you help him find the cellphone?

Input

There are many test cases (the number of test cases <= 100).
Each case starts with two number N and M, indicate the size of the mountaintop. Then, there is a map of N * M (see the format in Sample Input), "0" represent the empty space and "1" is the stone walls, "c" is X's location, "p" is the cellphone's location, and there are not stone walls in the grids of the X's location and the cellphone's location. (0 < n, m <= 1000)

Output

For each test case, output a integer in a line, indicating the minimum time that X spends to find his phone. the alien guarantees that X is able to find his phone.

Sample Input

7 10c01111p1100000011000000101000000100111001111000101000110000100000010012 2c00p

Sample Output

52

HINT


四维状态的宽搜。

启示:尽可能将一些琐碎的模块独立出来,比如找到四个方向上最近的石头(独立出来之后,可以更自由地控制对于特殊情况(如没有石头和紧临石头)的处理。


#include <cstdio>
#include <cstring>
 
const int mod = 4000010;
 
struct node
{
    int x;
    int y;
    int en;
    int ba;
    int t;
    //int f;///
};
node que[mod];
node u,v;
int n,m;
 
const int maxn = 1010;
char map[maxn][maxn];
int rightnear[maxn][maxn];
int leftnear[maxn][maxn];
int upnear[maxn][maxn];
int downnear[maxn][maxn];
bool vis[1010][1010][4][4];
 
void inc(int& l)
{
    l ++;
    if (l == mod)
        l = 0;
}
 
inline bool wall(int x,int y)
{
    return map[x][y] == '1';
}
 
inline bool inrange(int x,int y)
{
    return x>=1 && x<=n && y>=1 && y<=m;
}
 
const int dx[4] = {0,-1,0,1};
const int dy[4] = {-1,0,1,0};
 
int nearest(int x,int y,int d)
{
    switch (d)
    {
        case 0:
            if (leftnear[x][y] > -1)
                return y-leftnear[x][y]-1;
            break;
        case 2:
            if (rightnear[x][y] < m+1)
                return rightnear[x][y]-y-1;
            break;
        case 1:
            if (upnear[x][y] > -1)
                return x-upnear[x][y]-1;
            break;
        case 3:
            if (downnear[x][y] < n+1)
                return downnear[x][y]-x-1;
            break;
    }
    return -1;
}
 
int bfs(int sx,int sy,int tx,int ty)
{
    int l = 0;
    int r = 0;
 
    inc(r);
    que[r].t = 0;
    que[r].x = sx;
    que[r].y = sy;
    que[r].en = 3;
    que[r].ba = 3;
    memset(vis,0,sizeof vis);
    //que[r].f = 0;///
     
    vis[sx][sy][3][3] = true;
 
    while (l != r)
    {
        inc(l);
        u = que[l];
        //printf("Debug (%d,%d) t:%d en:%d ba:%d\n",u.x,u.y,u.t,u.en,u.ba);
        if (u.x == tx && u.y == ty)
        {
            //Debug
             
            /*
            int now = l;
            while (now != 0)
            {
                v = que[now];
                printf("Debug (%d,%d) t:%d en:%d ba:%d\n",v.x,v.y,v.t,v.en,v.ba);
                now = que[now].f;
            }
             
            */
            return u.t;
        }
 
        for (int d=0;d<4;d++)
        {
            v=u;
            v.x += dx[d];
            v.y += dy[d];
            v.t ++;
            if (inrange(v.x,v.y) && !wall(v.x,v.y) && !vis[v.x][v.y][v.ba][v.en])
            {
                vis[v.x][v.y][v.ba][v.en] = true;
                inc(r);
                que[r] = v;
                //que[r].f = l;//
            }
        }
 
        if (u.ba > 0)
        {
            for (int d=0;d<4;d++)
            {
                int _m = nearest(u.x,u.y,d);
                if (_m!=-1)
                {
                    v = u;
                    v.x += dx[d]*_m;
                    v.y += dy[d]*_m;
                    v.t ++;
                    v.ba --;
                    //if (inrange(v.x,v.y))
                    if (!vis[v.x][v.y][v.ba][v.en])
                    {
                        vis[v.x][v.y][v.ba][v.en] = true;
                        inc(r);
                        que[r] = v;
                        //que[r].f = l;//
                    }
                }
            }
        }
 
        if (u.en > 0)
        {
            for (int d=0;d<4;d++)
            {
                int cost = -1;
                v = u;
                if (!inrange(u.x+dx[d],u.y+dy[d]) || !wall(u.x+dx[d],u.y+dy[d]))
                    continue;
                do
                {
                    v.x += dx[d];
                    v.y += dy[d];
                    cost ++;
                }while (inrange(v.x,v.y)&&wall(v.x,v.y)&&cost<=u.en);
                if (!inrange(v.x,v.y) || cost > u.en)
                    continue;
                v.en -= cost;
                v.t ++;
                if (!vis[v.x][v.y][v.ba][v.en])
                {
                    vis[v.x][v.y][v.ba][v.en] = true;
                    inc(r);
                    que[r] = v;
                }
                //que[r].f = l;//
            }
        }
    }
}
 
int main()
{
    //freopen("ou.txt","w",stdout);
    while (scanf("%d%d",&n,&m)!=EOF)
    {
        int sx,sy,tx,ty;
        for (int i=1;i<=n;i++)
        {
            for (int j=1;j<=m;j++)
            {
                char tmp;
                do tmp = getchar();
                while (tmp!='c'&&tmp!='p'&&tmp!='0'&&tmp!='1');
                map[i][j] = tmp;
                if (tmp == 'c')
                {
                    map[i][j] = '0';
                    sx = i;
                    sy = j;
                }
                else if (tmp == 'p')
                {
                    map[i][j] = '0';
                    tx = i;
                    ty = j;
                }
            }
        }
 
        for (int i=1;i<=m;i++)
        {
            upnear[0][i] = -1;
            downnear[n+1][i] = n+1;
        }
        for (int i=1;i<=n;i++)
        {
            leftnear[i][0] = -1;
            rightnear[i][m+1] = m+1;
            for (int j=1;j<=m;j++)
            {
                if (map[i][j] != '1')
                {
                    leftnear[i][j] = leftnear[i][j-1];
                    upnear[i][j] = upnear[i-1][j];
                }
                else
                {
                    leftnear[i][j] = j;
                    upnear[i][j] = i;
                }
            }
            for (int j=m;j>0;j--)
            {
                if (map[i][j] != '1')
                    rightnear[i][j] = rightnear[i][j+1];
                else
                    rightnear[i][j] = j;
            }
        }
 
        for (int i=n;i>=1;i--)
            for (int j=1;j<=m;j++)
            {
                if (map[i][j] != '1')
                    downnear[i][j] = downnear[i+1][j];
                else
                    downnear[i][j] = i;
            }
 
        /*
        printf("Debug\n");
        for (int i=1;i<=n;i++)
        {
            for (int j=1;j<=m;j++)
            {
                printf("%d\t",downnear[i][j]);
            }
            printf("\n");
        }
        */
 
        int ans = bfs(sx,sy,tx,ty);
        printf("%d\n",ans);
    }
    return 0;
}
/**************************************************************
    Problem: 1267
    User: ssdut_team06
    Language: C++
    Result: Accepted
    Time:2082 ms
    Memory:112052 kb
****************************************************************/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值