ZOJ 3865 - Superbot(BFS)

题目:

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5477

题意:

给你一个n*m的地图,求出从@走到$的最小时间.使用按钮去控制人走的方向.

四个按钮的初始位置是(左,右,上,下).每p秒按钮会向右移动变成(下,左,右,上).

思路:

BFS.

vis[x][y][按钮方向][时间] 记录走过的位置.

在p秒来临前有三种: 按, 光标左移,光标右移

p秒时: 按后按钮动, 光标左移, 光标右移, 光标不动. (光标不动的情况时间要%4, 表示又回到了原来的位置.

AC.

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>

using namespace std;
int n, m, p;
char mp[15][15];
int r[5];
int dx[] = {0, 0, -1, 1}, dy[] = {-1, 1, 0, 0};
struct node {
    int x, y, id, step;
    node(int xx, int yy, int ii, int s) {
        x = xx; y = yy; id = ii; step = s;
    }
//    bool operator < (const node&A) const {
//        return step > A.step;
//    }
};
queue<node> que;
int edx, edy, stx, sty;
bool vis[15][15][10][500];

bool ok(int tx, int ty)
{
    if(tx < 0 || tx >= n || ty < 0 || ty >= m
        || mp[tx][ty] == '*') return false;
    return true;
}
void rot()
{
    int t = r[3];
    r[3] = r[2]; r[2] = r[1]; r[1] = r[0]; r[0] = t;
}
void bfs()
{
    memset(vis, 0, sizeof(vis));
    int nx, ny, iid;
    node no = node(stx, sty, 0, 0);
    vis[stx][sty][0][0] = 1;
    que.push(no);

    while(que.size()) {
        no = que.front(); que.pop();
        if(no.x == edx && no.y == edy) {
            printf("%d\n", no.step);
            return;
        }

        int x = no.x, y = no.y, id = no.id, s = no.step;
        s++;

        if(s % p == 0) { //旋转
            iid = (id-1+4)%4;//原位按
            nx = x + dx[r[id]]; ny = y + dy[r[id]];
            if(ok(nx, ny) && !vis[nx][ny][r[iid]][s]) {
                no = node(nx, ny, iid, s);
                vis[nx][ny][r[iid]][s] = 1;
                que.push(no);
            }

            iid = (id-1+4)%4;//不动
            if(!vis[x][y][r[iid]][s%4]) {
                no = node(x, y, iid, s);
                vis[x][y][r[iid]][s] = 1;
                que.push(no);
            }

            iid = id;//右移
            if(!vis[x][y][r[iid]][s]) {
                no = node(x, y, iid, s);
                vis[x][y][r[iid]][s] = 1;
                que.push(no);
            }

            iid = (id-2+4)%4;//左移
            if(!vis[x][y][r[iid]][s]) {
                no = node(x, y, iid, s);
                vis[x][y][r[iid]][s] = 1;
                que.push(no);
            }
        }
        else {//不旋转

            nx = x + dx[r[id]]; ny = y + dy[r[id]];//按
            if(ok(nx, ny) && !vis[nx][ny][r[id]][s] ) {
                no = node(nx, ny, id, s);
                vis[nx][ny][r[id]][s] = 1;
                que.push(no);
            }

            iid = (id-1+4)%4;//左移
            if(!vis[x][y][r[iid]][s]) {
                no = node(x, y, iid, s);
                vis[x][y][r[iid]][s] = 1;
                que.push(no);
            }

            iid = (id+1+4)%4;//右移
            if(!vis[x][y][r[iid]][s]) {
                no = node(x, y, iid, s);
                vis[x][y][r[iid]][s] = 1;
                que.push(no);
            }
        }
    }
    printf("YouBadbad\n");
    return;
}

int main()
{
//freopen("in", "r", stdin);
    int T;
    scanf("%d", &T);
    while(T--) {
        for(int i = 0; i < 4; ++i) r[i] = i;

        while(que.size()) que.pop();

        scanf("%d %d %d", &n, &m, &p);
        for(int i = 0; i < n; ++i) {
            scanf("%s", mp[i]);
            for(int j = 0; j < m; ++j) {
                if(mp[i][j] == '$') {
                    edx = i; edy = j;
                }
                if(mp[i][j] == '@') {
                    stx = i; sty = j;
                }
            }
        }
        //printf("%d %d\n", edx, edy);
        bfs();
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值