hiho #1308 : 搜索二·骑士问题
#1308 : 搜索二·骑士问题
描述
小Hi:小Ho你会下国际象棋么?
小Ho:应该算会吧,我知道每个棋子的移动方式,马走日象飞田什么的...
小Hi:象飞田那是中国象棋啦!
小Ho:哦,对。国际象棋好像是走斜线来着。
小Hi:不过马走日倒是对了。国际象棋中的马一般叫做骑士,关于它有个很有意思的问题。
小Ho:什么啊?
小Hi:骑士巡游问题,简单来说就是关于在棋盘上放置若干个骑士,然后探究移动这些骑士是否能满足一定的而要求。举个例子啊:一个骑士从起始点开始,能否经过棋盘上所有的格子再回到起点。
小Ho:哦,看上去好像很难的样子。
小Hi:其实也还好了。简单一点的比如棋盘上有3个骑士,能否通过若干次移动走到一起。
小Ho:能够么?
小Hi:当然能够了。由于骑士特殊的移动方式,放置在任何一个初始位置的骑士,都可以通过若干次移动到达棋盘上任意一个位置。
小Ho:那么只要选定一个位置,把它们全部移动过去就好了是吧?
小Hi:是的,那么这里又有另一个问题了:要选择哪一个位置汇合,使得3个骑士行动的总次数最少?
小Ho:嗯,这个好像不是很难,让我想一想。
输入
第1行:1个正整数t,表示数据组数,2≤t≤10。
第2..t+1行:用空格隔开的3个坐标, 每个坐标由2个字符AB组成,A为'A'~'H'的大写字母,B为'1'~'8'的数字,表示3个棋子的初始位置。
输出
第1..t行:每行1个数字,第i行表示第i组数据中3个棋子移动到同一格的最小行动步数。
- 样例输入
-
2
A1 A1 A1
B2 D3 F4 - 样例输出
-
0
2
思路:
利用队列做bfs,求出当前位置到棋盘上所有位置的最短距离,然后,三个棋子到棋盘位置的最短距离和
AC代码:
#include "iostream"
#include "string.h"
#include "queue" using namespace std; typedef pair<int, int> pii;
char ss[];
int vis[][][];
int d[][] = { { -, },{ -,- },{ -,- },{ -, },{ ,- },{ , },{ ,- },{ , } };
int step = ; pii pos; //马位置 bool in(pii p)
{
if (p.first < || p.second < || p.first> || p.second>)
return false;
else
return true;
} void bfs(int vi[][])
{
step = ;
queue<pii> q;
memset(vi, -, );
q.push(pos);
vi[pos.first][pos.second] = ; while (!q.empty())
{
pii pfront = q.front();
q.pop();
for (int i = ; i < ; i++)
{
pii temp;
temp.first = pfront.first + d[i][];
temp.second = pfront.second + d[i][];
if (in(temp) && vi[temp.first][temp.second] == -)
{
vi[temp.first][temp.second] = vi[pfront.first][pfront.second] + ;
q.push(temp);
}
}
}
} int main()
{
int t;
cin >> t;
while (t--)
{
scanf("%s", ss);
pos = make_pair(ss[] - 'A', ss[] - '');
bfs(vis[]); scanf("%s", ss);
pos = make_pair(ss[] - 'A', ss[] - '');
bfs(vis[]); scanf("%s", ss);
pos = make_pair(ss[] - 'A', ss[] - '');
bfs(vis[]); int ans = 1e9;
for (int i = ; i < ; i++)
{
for (int j = ; j < ; j++)
{
int temp = ;
for (int k = ; k < ; k++)
{
temp += vis[k][i][j];
}
if (temp < ans)
ans = temp;
}
}
cout << ans << endl;
}
}
补充:
提供另一种思路,因为是8x8的棋盘,可以模拟成8进制的一个数,这样3个旗子就是一个6位的8进制数。
由此可以通过一个大小为8^6的布尔数组来进行状态的判重。而每一次的状态转移也从原来的仅枚举8个方向,变成了枚举骑士加枚举方向,一共有3*8=24种可能。
此方法的伪代码为:
queue.push( initialStatus ) // 将初始的8进制数加入队列中
while (!queue.isEmpty())
now_status = queue.pop() // 弹出队列头元素
For i = 1 .. 3
// 枚举移动的其实
For j = 1 .. 8
// 枚举8种可能的移动
next_status = move(now_status, i, j) // 移动骑士并记录状态
If (next_status is valid AND not visited[ next_status ])
step[ next_status ] = step[ now_status ] + 1
queue.push( next_status )
If (check(next_status)) Then
// 检查这个八进制数是否满足3个坐标重合
Return step[ next_status ]
End If
End If
End For
End While
在进行检查是否已经走到一起时,可以通过一个位运算来做:
check(status):
Return ((status and 0x3f) == ((status rsh 6) and 0x3f)) and (((status rsh 6) and 0x3f) == ((status rsh 12) and 0x3f))
// rsh表示右移操作
小Ho:哦,这样就可以不用计算出每个骑士走到每个点的步数,而是在过程中就有可能直接求解到最先汇合位置的步数。
小Hi:对,不过这个算法中状态的转移会稍微复杂一点。你可以选择一个你比较喜欢的方法来实现。
小Ho:好!
hiho #1308 : 搜索二·骑士问题的更多相关文章
- 【hihocoder 1308】搜索二·骑士问题
[题目链接]:http://hihocoder.com/problemset/problem/1308 [题意] [题解] 用bfs处理出3个骑士到每个点的最短路; 然后枚举最后3个骑士到了哪一个点. ...
- hihoCoder 1308:搜索二·骑士问题(BFS预处理)
题目链接 题意 中文题意. 思路 对于每一个骑士,可以先预处理出到达地图上某个点的需要走的步数,然后最后暴力枚举地图上每一个点,让三个骑士走过的距离之和最小即可. #include <bits/ ...
- hihoCoder搜索二·骑士问题
#include <stdio.h> #include <string.h> #include <math.h> #include <algorithm> ...
- lintcode:搜索二维矩阵II
题目 搜索二维矩阵 II 写出一个高效的算法来搜索m×n矩阵中的值,返回这个值出现的次数. 这个矩阵具有以下特性: 每行中的整数从左到右是排序的. 每一列的整数从上到下是排序的. 在每一行或每一列中没 ...
- lintcode :搜索二维矩阵
题目: 搜索二维矩阵 写出一个高效的算法来搜索 m × n矩阵中的值. 这个矩阵具有以下特性: 每行中的整数从左到右是排序的. 每行的第一个数大于上一行的最后一个整数. 样例 考虑下列矩阵: [ [1 ...
- hiho欧拉路·二 --------- Fleury算法求欧拉路径
hiho欧拉路·二 分析: 小Ho:这种简单的谜题就交给我吧! 小Hi:真的没问题么? <10分钟过去> 小Ho:啊啊啊啊啊!搞不定啊!!!骨牌数量一多就乱了. 小Hi:哎,我就知道你会遇 ...
- 算法进阶面试题05——树形dp解决步骤、返回最大搜索二叉子树的大小、二叉树最远两节点的距离、晚会最大活跃度、手撕缓存结构LRU
接着第四课的内容,加入部分第五课的内容,主要介绍树形dp和LRU 第一题: 给定一棵二叉树的头节点head,请返回最大搜索二叉子树的大小 二叉树的套路 统一处理逻辑:假设以每个节点为头的这棵树,他的最 ...
- LintCode-38.搜索二维矩阵 II
搜索二维矩阵 II 写出一个高效的算法来搜索m×n矩阵中的值,返回这个值出现的次数. 这个矩阵具有以下特性: 每行中的整数从左到右是排序的. 每一列的整数从上到下是排序的. 在每一行或每一列中没有重复 ...
- LeetCode74.搜索二维矩阵
74.搜索二维矩阵 描述 编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值.该矩阵具有如下特性: 每行中的整数从左到右按升序排列. 每行的第一个整数大于前一行的最后一个整数. 示例 示 ...
随机推荐
- TCP协议基础(一)
TCP为应用层提供的服务 提供进程和进程之间的通信 答: 怎么区分服务目的主机上的哪个进程呢? 通过提供端口号(well-known port), 如Telnet 23,DNS 53, HTTP 80 ...
- PTA(Basic Level)1047.编程团体赛
编程团体赛的规则为:每个参赛队由若干队员组成:所有队员独立比赛:参赛队的成绩为所有队员的成绩和:成绩最高的队获胜. 现给定所有队员的比赛成绩,请你编写程序找出冠军队. 输入格式: 输入第一行给出一个正 ...
- 查找担保圈-step3-获取担保圈路径
USE [test] GO /****** Object: StoredProcedure [dbo].[p01_get_group_path] Script Date: 2019/7/8 14:40 ...
- 2. zookeeper介绍及集群搭建
ZooKeeper 概述 Zookeeper 是一个分布式协调服务的开源框架. 主要用来解决分布式集群中 应用系统的一致性问题,例如怎样避免同时操作同一数据造成脏读的问题. ZooKeeper 本质上 ...
- 基于 Vue.js 2.0 酷炫自适应背景视频登录页面的设计『转』
本文讲述如何实现拥有酷炫背景视频的登录页面,浏览器窗口随意拉伸,背景视频及前景登录组件均能完美适配,背景视频可始终铺满窗口,前景组件始终居中,视频的内容始终得到最大限度的保留,可以得到最好的视觉效果. ...
- 【转】在C#中使用Json.Net进行序列化和反序列化及定制化
作者:Minotauros 原文地址:在C#中使用Json.Net进行序列化和反序列化及定制化 序列化(Serialize)是将对象转换成字节流,并将其用于存储或传输的过程,主要用途是保存对象的状态, ...
- thinkPHP验证码报错: Call to undefined function captcha_src()
问题出现的原因可能有: 1. captcha扩展缺失: 2. captcha扩展与当前thinkPHP版本不兼容. thinkPHP6.0以下版本只能使用 captcha2.0以下版本,不支持2.0版 ...
- 移动端、pc端通用点击复制
点击复制 function copyArticle(event){ const range = document.createRange(); range.selectNode(document.ge ...
- ubuntu - 如何以root身份使用图形界面管理文件?
nautilus 是gnome的文件管理器,但是如果不是root账号下,权限受限,我们可以通过以下方式以root权限使用! 一,快捷键“ctrl+alt+t”,调出shell. 二,在shell中输入 ...
- docker中centos7安装ssh服务
来源:https://blog.csdn.net/qq_32969313/article/details/64919735 docker安装好后,自己动手做个自己的docker镜像,首先需要从服务器p ...