题面

首先我们可以发现,在每一次 BFS 时按照 \(A→B→C\) 的顺序枚举遍历肯定是字典序最小的。

然后就是普通的 BFS 了。

我们考虑使用 \(\text{STL map}\) 来存储起点状态到当前状态所需的最少步数,以及到达它的上一个状态与上一个操作代号。

具体实现可参考代码。

#include <bits/stdc++.h>

using namespace std;

int n, m;
string start = "12345678", endd; //起始状态和目标状态
map <string, int> dist; //存储到达当前状态的最少步数
map <string, pair <char, string> > ans; //到达当前状态的上一个状态和操作代号
string q[100003], sum; //BFS 时的队列 和 答案
int hh, tt; //队头和队尾指针
char g[3][5]; //临时矩阵,转移的时候用 inline void getjuzhen(string x) //从压缩的状态变成矩阵
{
for (int i = 1; i <= 4; i+=1) g[1][i] = x[i - 1]; //第一排
g[2][4] = x[4], g[2][3] = x[5], g[2][2] = x[6], g[2][1] = x[7]; //第二排
} inline string getzhuangtai() //从矩阵压缩成状态
{
string now = "";
for (int i = 1; i <= 4; i+=1) now = now + g[1][i]; //第一排
for (int j = 4; j >= 1; j-=1) now = now + g[2][j]; //第二排
return now;
} inline string getA(string x) //A 操作
{
getjuzhen(x);
for (int i = 1; i <= 4; i+=1) swap(g[1][i], g[2][i]); //将第一行与第二行交换
return getzhuangtai();
} inline string getB(string x) //B 操作
{
getjuzhen(x);
swap(g[1][1], g[1][4]), swap(g[2][1], g[2][4]);
swap(g[1][2], g[1][4]), swap(g[2][2], g[2][4]);
swap(g[1][3], g[1][4]), swap(g[2][3], g[2][4]);
//依次交换每一列
return getzhuangtai();
} inline string getC(string x) //C 操作
{
getjuzhen(x);
swap(g[1][2], g[1][3]);
swap(g[1][2], g[2][3]);
swap(g[1][2], g[2][2]);
//中间的 4 个数依次交换
return getzhuangtai();
} inline void bfs(string s, string t) //BFS
{
if (s == t) return; //如果目标状态与开始状态相同就不要搜索了
hh = tt = 0;
q[0] = s; //队列中只有 1 个元素
while (hh <= tt) //队列不为空
{
string c = q[hh++]; //取出队头元素
string h[3];
h[0] = getA(c); //A 操作
h[1] = getB(c); //B 操作
h[2] = getC(c); //C 操作
for (int i = 0; i < 3; i+=1) //枚举每一个操作
{
if (dist[h[i]] == 0) //如果当前状态还没有遍历过
{
dist[h[i]] = dist[c] + 1; //记录最少步数
ans[h[i]] = (make_pair)(i + 'A', c); //记录转移过来的操作代号和状态
if (h[i] == t) return; //找到了目标状态
q[++tt] = h[i]; //加入队列
}
}
}
} int main()
{
for (int i = 1; i <= 8; i+=1)
{
int u; cin >> u;
endd = endd + (char)(u + '0'); //目标状态
}
bfs(start, endd);
cout << dist[endd] << endl; //输出最少步数
if (dist[endd] == 0) return 0; //注意特判
while (endd != start) //推出每一步的操作
{
sum = sum + ans[endd].first; //记录每一步的操作
endd = ans[endd].second; //向前推
}
reverse(sum.begin(), sum.end()); //记得要反转,因为我们存储的操作是反序的
cout << sum << endl; //输出操作序列
return 0;
}

题解【洛谷P2730】魔板 Magic Squares的更多相关文章

  1. 洛谷 P2730 魔板 Magic Squares 解题报告

    P2730 魔板 Magic Squares 题目背景 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 题目描述 ...

  2. 洛谷 P2730 魔板 Magic Squares

    P2730 魔板 Magic Squares 题目背景 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 题目描述 ...

  3. [洛谷P2730] 魔板 Magic Squares

    洛谷题目链接:魔板 题目背景 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 题目描述 我们知道魔板的每一个方格都 ...

  4. 洛谷 - P2730 - 魔板 Magic Squares - bfs

    写状态转移弄了很久,老了,不记得自己的数组是怎么标号的了. #include <bits/stdc++.h> using namespace std; #define ll long lo ...

  5. 洛谷P2730 魔板 [广搜,字符串,STL]

    题目传送门 魔板 题目背景 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 题目描述 我们知道魔板的每一个方格都有 ...

  6. P2730 魔板 Magic Squares

    题目背景 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 题目描述 我们知道魔板的每一个方格都有一种颜色.这8种颜 ...

  7. P2730 魔板 Magic Squares (搜索)

    题目链接 Solution 这道题,我是用 \(map\) 做的. 具体实现,我们用一个 \(string\) 类型表示任意一种情况. 可以知道,排列最多只有 \(8!\) 个. 然后就是直接的广搜了 ...

  8. 哈希+Bfs【P2730】 魔板 Magic Squares

    没看过题的童鞋请去看一下题-->P2730 魔板 Magic Squares 不了解康托展开的请来这里-->我这里 至于这题为什么可以用康托展开?(瞎说时间到. 因为只有8个数字,且只有1 ...

  9. 【简●解】 LG P2730 【魔板 Magic Squares】

    LG P2730 [魔板 Magic Squares] [题目背景] 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 ...

  10. [USACO3.2]魔板 Magic Squares

    松下问童子,言师采药去. 只在此山中,云深不知处.--贾岛 题目:魔板 Magic Squares 网址:https://www.luogu.com.cn/problem/P2730 这是一张有8个大 ...

随机推荐

  1. 自学Java第一章——《Java概述》

    1.1 Java历史 Java诞生于SUN(Stanford University Network),09年SUN被Oracle(甲骨文)收购. Java之父是詹姆斯.高斯林(James Goslin ...

  2. Asp.net core 2.x/3.x 的 Globalization 和 localization 的使用 (一) 使用方法

    由于Api的接口需要返回多语言,因此参考了网上很多篇文章,,有些文章写的太过于理论,看起来比较费劲,今天下午搞了一个下午,总结了一下经验,, 做这个功能时,主要参考了两篇文章: https://blo ...

  3. 每日一练_PAT_B_PRAC_1004客似云来

    题目描述 NowCoder开了一家早餐店,这家店的客人都有个奇怪的癖好:他们只要来这家店吃过一次早餐,就会每天都过来:并且,所有人在这家店吃了两天早餐后,接下来每天都会带一位新朋友一起来品尝.于是,这 ...

  4. python 存储数据

    如何进行数据存储,很多程序都要求用户输入某种信息,如让用户存储游戏首选项或提供要可视化的数据. 使用模块json进行数据存储. 1.1.使用json.dump()和json.load() #-*- e ...

  5. 三、Mongodb Java中的使用

    添加maven依赖 <!--mongodb 驱动--> <dependency> <groupId>org.mongodb</groupId> < ...

  6. .Net Core中IOC容器的使用

    打代码之前先说一下几个概念,那就是什么是IOC.DI.DIP 虽然网上讲这些的已经有很多了,我这里还是要再赘述一下 IOC容器就是一个工厂,负责创建对象的 IOC控制反转:只是把上端对下端的依赖,换成 ...

  7. Go语言实现:【剑指offer】翻转单词顺序列

    该题目来源于牛客网<剑指offer>专题. 例如,"student. a am I",正确的句子应该是"I am a student." Go语言实 ...

  8. 使用Python打造一款间谍程序

    知识点 这次我们使用python来打造一款间谍程序 程序中会用到许多知识点,大致分为四块 win32API  此处可以在MSDN上查看 Python基础重点在cpytes库的使用,使用方法请点击此处 ...

  9. JAVA System.exit(0) 和 System.exit(1) 的区别

    System.exit(int state) 方法都是来结束当前运行的java虚拟机.所有System.exit(1).System.exit(0) 执行后都会退出程序. state为0时时正常退出, ...

  10. rsync命令 SCP命令

    快速查询scp:     scp  各种参数   源地址文件    目的地址文件   从本地复制到远程:        scp   [[user@]host1:]file1 ... [[user@]h ...