关闭

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

219人阅读 评论(0) 收藏 举报
分类:

题目链接

可以直接跑三次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;
}
0
0
查看评论

【hihocoder 1308】搜索二·骑士问题

【题目链接】:http://hihocoder.com/problemset/problem/1308【题意】 【题解】 用bfs处理出3个骑士到每个点的最短路; 然后枚举最后3个骑士到了哪一个点. 把3个骑士的最短路加起来取最小值就好; 【Number Of WA】 0 ...
  • harlow_cheng
  • harlow_cheng
  • 2017-04-29 21:29
  • 130

ACM:搜索算法专题(2)——骑士问题

题目描述:     在国际象棋的棋盘上放置3个骑士的棋子,按照骑士的移动规则移动这3个棋子,使其到达同一个位置,求最少的移动次数。 解答:     本题不难。首先说明一下国际象棋的规则,棋盘由8×8=64个黑白相间的格子组成,...
  • octopusflying
  • octopusflying
  • 2016-05-30 09:51
  • 1440

每日一算法:骑士遍历问题

说明骑士旅游(Knight tour)在十八世纪初倍受数学家与拼图迷的注意,它什么时候被提出已不可考,骑士的走法为西洋棋的走法,骑士可以由任一个位置出发,它要如何走完[所有的位置? 解法骑士的走法,基本上可以使用递回来解决,但是纯綷的递回在维度大时相当没有效率,一个聪明的解法由J.C. Warns...
  • qq523176585
  • qq523176585
  • 2013-11-11 17:20
  • 1294

搜索二·骑士问题

描述 国际象棋棋盘上有3个骑士,能否通过若干次移动走到一起。要选择一个位置汇合,使得3个骑士行动的总次数最少? 输入 第1行:1个正整数t,表示数据组数,2≤t≤10。 第2..t+1行:用空格隔开的3个坐标, 每个坐标由2个字符AB组成,A为'A'~'H'的大写字...
  • Tramp_1
  • Tramp_1
  • 2016-05-24 10:30
  • 469

hiho一下 第九十九周 #1308 : 搜索二·骑士问题 【宽度优先搜索】

#1308 : 搜索二·骑士问题 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi:小Ho你会下国际象棋么? 小Ho:应该算会吧,我知道每个棋子的移动方式,马走日象飞田什么的... 小Hi:象飞田那是中国象棋啦! 小Ho:哦,对。国...
  • leibniz_zhang
  • leibniz_zhang
  • 2016-11-06 22:17
  • 398

骑士周游问题(暴力解决:回溯法)

建议测试数据 3 0 或 4 0
  • H992109898
  • H992109898
  • 2016-02-16 13:35
  • 1908

骑士巡游问题算法

骑士巡游或叫马步遍历问题描述:在n*n的棋盘上,假设一个骑士按象棋中“马”的走法,从初始坐标(x1,y1)出发,要求无重复地走遍棋盘中的每一个位置(每个点必须经过一次且只能是一次 )。请编写程序,为骑士求解巡游“路线”(或无解)。代码:#include #include using namespac...
  • zhengzhiren
  • zhengzhiren
  • 2009-03-02 20:36
  • 4899

骑士巡游问题 python

# -*- coding: utf-8 -*- import numpy as np def printP():     global n     global pieces     for i in range(n): ...
  • haitaolang
  • haitaolang
  • 2017-01-10 17:36
  • 587

hihoCoder搜索二·骑士问题

#include <stdio.h> #include <string.h> #include <math.h> #include <algorithm> #include <iostream> using namespace std; #...
  • KEYboarderQQ
  • KEYboarderQQ
  • 2016-07-03 16:04
  • 362

骑士旅行问题(骑士走棋盘)

一个骑士在棋盘中,给予其一个初始值,
  • firechungelaile
  • firechungelaile
  • 2014-09-28 00:18
  • 878
    个人资料
    • 访问:207778次
    • 积分:7068
    • 等级:
    • 排名:第3865名
    • 原创:522篇
    • 转载:3篇
    • 译文:0篇
    • 评论:12条
    文章分类
    最新评论