HIHO #1308 : 搜索二·骑士问题

题目链接

可以直接跑三次bfs,也可以使用18位的二进制表示3个人的状态,一次bfs,因为坐标在0-7,所以一个数字只用3位就够了,然后6个数字,一共18位就够了

#include<bits/stdc++.h>
using namespace std;
#define cl(a,b) memset(a,b,sizeof(a))
#define fastIO ios::sync_with_stdio(false);cin.tie(0);
#define LL long long
#define pb push_back
#define gcd __gcd


#define For(i,j,k) for(int i=(j);i<=k;i++)
#define lowbit(i) (i&(-i))
#define _(x) printf("%d\n",x)

typedef vector<LL> vec;
const double EPS = 1e-8;
const int maxn = 5e6+10;
const int inf  = 1 << 28;

bool vis[1<<20];
int step[1<<20];
int len  = (1 <<  6) - 1;
int len2 = (1 << 12) - 1;
int len3 = (1 << 18) - 1;

int dir[][8]= {{1,-1,2,-2,-2,-1,1,2},{2,2,1,1,-1,-2,-2,-1}};
bool check(int x) {
    if( (x & len) == ((x >> 6) & len) && (x & len) == ((x >> 12) & len) ) return true;
    return false;
}

int getPos(int num,int dx,int dy) { // num <==> ... ... 6位,前3位x,后三位y
    int y = num & 7;// 111 & num
    int x = num >> 3 & 7;

    int xx = x + dx;
    int yy = y + dy;

    if(xx < 0 || yy < 0 || xx >= 8 || yy >= 8)return -1;

    return xx << 3 | yy;
}


int bfs(int s) {
    queue<int> q;
    cl(vis,false);
    cl(step,0);

    vis[s] = true;
    step[s] = 0;
    q.push(s);

    while(!q.empty()) {
        int x = q.front();q.pop();
        if(check(x)) {
            return step[x];
        }

        int aim;
        for(int i=0; i<=12; i+=6) {
            int cur = x >> i & len;// three people

            for(int j=0; j<8; j++) {

                int tmp = getPos(cur,dir[0][j],dir[1][j]);

                if(tmp == -1)continue;

                if(i ==  0) aim = x & (len3 ^ len);
                if(i ==  6) aim = x & (len3 ^ len2) | (x & len);
                if(i == 12) aim = x & len2;

                aim |= (tmp << i);
                if(!vis[aim]) {
                    vis[aim] = true;
                    q.push(aim);
                    step[aim] = step[x] + 1;
                }
            }
        }
    }
}

char str[4];
int main() {

    int T;
    scanf("%d",&T);
    while(T--) {
        int k = 12;
        int state = 0;
        for(int i=0; i<3; i++) {
            scanf("%s",str);
            int x = str[0] - 'A';
            int y = str[1] - '1';
            state |=(x << 3 | y) << k;
            k-=6;
        }

        printf("%d\n",bfs(state));
    }
    return 0;
}

跑三次bfs的

#include<bits/stdc++.h>
using namespace std;
#define cl(a,b) memset(a,b,sizeof(a))
#define fastIO ios::sync_with_stdio(false);cin.tie(0);
#define LL long long
#define pb push_back
#define gcd __gcd

#define For(i,j,k) for(int i=(j);i<k;i++)
#define lowbit(i) (i&(-i))
#define _(x) printf("%d\n",x)

const double EPS = 1e-8;
const int maxn = 1e6+10;
const int inf  = 1 << 28;

int dis[3][10][10];
bool vis[10][10];
int dir[][8]= {{1,-1,2,-2,-2,-1,1,2},{2,2,1,1,-1,-2,-2,-1}};
void bfs(int t,int x,int y){
    queue<pair<int,int> > q;
    cl(vis,false);
    cl(dis[t],0x3f);

    q.push(make_pair(x,y));
    vis[x][y] = true;
    dis[t][x][y] = 0;

    while(!q.empty()){
        pair<int,int> x = q.front();q.pop();

        for(int i=0;i<8;i++){
            int xx = x.first  + dir[0][i];
            int yy = x.second + dir[1][i];
            if(xx < 0 || yy < 0 || xx >= 8 || yy >= 8 || vis[xx][yy])continue;
            vis[xx][yy] = true;
            q.push(make_pair(xx,yy));
            dis[t][xx][yy] = dis[t][x.first][x.second] + 1;

        }
    }
}

char str[3];
int main(){
    int T;scanf("%d",&T);
    while(T--){
        for(int i=0;i<3;i++){
            scanf("%s",str);
            bfs(i,str[0]-'A',str[1]-'1');
        }
        int ans = inf;
        for(int i=0;i<8;i++)for(int j=0;j<8;j++){
            ans = min (ans, dis[0][i][j]+dis[1][i][j]+dis[2][i][j]);
        }
        printf("%d\n",ans);
    }
    return 0;
}
    原文作者:骑士周游问题
    原文地址: https://blog.csdn.net/u013167299/article/details/52350061
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞