BFS

BFS -> 僵尸感染 -> 队列

每个点状态的数量 ,每个状态访问一次,想办法将状态转换为int(类似hash)

int visted = [x][y][状态数量];
Queue queue;

void bfs(起点){
if起点符合退出条件,return

  起点入队
  while(队列不为空){
      当前临时点 = queue出队
      for(各个方向遍历){
          根据当前临时点得到下一个点的位置
         if(下一个点的visted没有访问过&&其他条件成立)
             下一个点入队
             更新下一个的信息(比如到达step)
             如果符合退出条件,return
             else 继续
         }
      } 
 }

}

POJ 1324

#include <cstdio>
#include <iostream>

using namespace std;
#define SIZE 20
#define LENGTH 8
#define SNAKE_STATES 16384 //状态数量,以蛇头为起点,向后的每个点都有4中状态(取整),就提取了特征值

int snake[LENGTH][2];
int stone[SIZE * SIZE][2];

int visited[SIZE + 1][SIZE + 1][SNAKE_STATES];
typedef struct Element{
    int x;
    int y;
    int state;
    int step;
} Element;

Element Queue[SIZE * SIZE * SNAKE_STATES];
int head, tail;


int direct[3][3] = {
    0, 0, 0,
    3, 0, 1,
    0, 2, 0,
};

int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};

int getState(int Len){
    int state = 0;
    for(int i = Len - 1; i > 0; i--){
        int x = snake[i][0] - snake[i - 1][0];
        int y = snake[i][1] - snake[i - 1][1];
        x+=1;
        y+=1;
        int D = direct[x][y];
        state = state * 4 + D;
    }
    return state;
}

int isStone(int x, int y, int K){
    for(int i = 0; i < K; i++){
        if(x == stone[i][0] && y == stone[i][1])
            return 1;
    }
    return 0;
}

int isSnake(int x, int y, int state, int L, int nx, int ny){
    snake[0][0] = x;
    snake[0][1] = y;
    for(int i = 1; i < L; i++){
        int D = state % 4;
        state = state / 4;
        snake[i][0] = snake[i - 1][0] + dx[D];
        snake[i][1] = snake[i - 1][1] + dy[D];
    }
    for(int i = 0; i < L; i++){
        if(nx == snake[i][0] && ny == snake[i][1]){
            return 1;
        }
    }
    return 0;
}

int getMinStep(int M, int N, int L, int K){
    Queue[tail].x = snake[0][0];
    Queue[tail].y = snake[0][1];
    Queue[tail].state = getState(L);
    Queue[tail].step = 0;
    visited[Queue[tail].x][Queue[tail].y][Queue[tail].state] = 1;
    if(Queue[tail].x == 1 && Queue[tail].y == 1) return 0;
    tail++;
    while(head < tail){
        Element curState = Queue[head++];
        //cout << "out " <<  curState.x << " " << curState.y << " " << curState.step << " " << curState.state << endl;
        for(int i = 0; i < 4; i++){
            int nx = curState.x + dx[i];
            int ny = curState.y + dy[i];
            int nd;
            if(i >= 2) nd = i - 2;
            else nd = i + 2;
            if(nx >= 1 && nx <= M && ny >= 1 && ny <= N){
                int mask = (1 << (2 * L - 2)) - 1;
                int nState = ((curState.state * 4) & mask) + nd;
                if(!visited[nx][ny][nState] && !isStone(nx, ny, K) && !isSnake(curState.x, curState.y, curState.state, L, nx, ny)){
                    Queue[tail].x = nx;
                    Queue[tail].y = ny;

                    Queue[tail].state = nState;
                    Queue[tail].step = curState.step + 1;

                    //cout << "in " <<  nx << " " << ny << " " << Queue[tail].step << " " << nState << endl;
                    if(nx == 1 && ny == 1) return Queue[tail].step;

                    tail++;
                    visited[nx][ny][nState] = 1;
                }
            }
        }
    }
    return -1;
}

int main(){
    //freopen("input.txt", "r", stdin);
    int nC = 1;
    while(1){
        int M, N, L;
        cin >> M >> N >> L;
        if(M + N + L == 0) break;

        for(int i = 0; i < L; i++){
            cin >> snake[i][0] >> snake[i][1];
        }
        int K;
        cin >> K;
        for(int i = 0; i < K; i++){
            cin >> stone[i][0] >> stone[i][1];
        }
        head = 0;
        tail = 0;
        for(int i = 0; i <= M; i++){
            for(int j = 0; j <= N; j++){
                for(int k = 0; k < SNAKE_STATES; k++){
                    visited[i][j][k] = 0;
                }
            }
        }
        int minStep = getMinStep(M, N, L, K);
        cout << "Case " << nC <<": "<< minStep << endl;
        nC++;
    }


    return 0;
}
  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值