[图bfs] Knight Moves HDU1372,UVa536

题目描述

输入标准 8 8 国际象棋棋盘上的两个格子,分别作为起点和终点(列用 a ~ h 表示, 行用 1 ~ 8 表示), 求马最少需要多少不从起点跳到终点。
这里写图片描述

题解

本题可以看作一个简单的bfs求最短路径问题。值得注意的是,可以使用位运算,将两个数用一个int型表示,从而避免使用结构体。AC代码如下:

AC代码

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;

const int dx[8]={-2,-2,-1,-1,1,1,2,2};
const int dy[8]={-1,1,-2,2,-2,2,-1,1};

int mp[10][10];
char be[5], en[5];

int code(int bi, int bj){return (bi<<4)|bj;}
void recode(int cn, int &ni, int &nj){ nj = cn&0xf; ni = (cn>>4)&0xf;}

void bfs(int start, int aim){
    queue<int> qu;
    while(!qu.empty()) qu.pop();
    qu.push(start);
    while(!qu.empty()){
        int s = qu.front(); qu.pop();
        int ni, nj;
        recode(s, ni, nj);
        for(int i = 0; i<8; i++){
            int bi = ni+dx[i], bj = nj+dy[i];
            if(!mp[bi][bj] && 0<=bi && bi <8 && 0<=bj && bj<8){
                mp[bi][bj] = mp[ni][nj]+1;
                if(code(bi, bj) == aim) return;
                else qu.push(code(bi, bj));
            }
        }
    }
}

int solve(){
    int start = ((be[0]-'a')<<4)|(be[1]-'1');
    int aim = ((en[0]-'a')<<4)|(en[1]-'1');
    if(start == aim) return 0;
    bfs(start, aim);
    int ni, nj;
    recode(aim, ni, nj);
    return mp[ni][nj];
}

int main(){
    while(scanf("%s%s", be, en) != EOF){
        memset(mp, 0, sizeof(mp));
        printf("To get from %s to %s takes %d knight moves.\n", be, en, solve());
    }
}

猜你喜欢

转载自blog.csdn.net/loyxCCS/article/details/79998210