松下问童子,言师采药去。

只在此山中,云深不知处。——贾岛

题目:魔板 Magic Squares

网址:https://www.luogu.com.cn/problem/P2730

这是一张有8个大小相同的格子的魔板:

1 2 3 4

8 7 6 5

题目描述

我们知道魔板的每一个方格都有一种颜色。这8种颜色用前8个正整数来表示。可以用颜色的序列来表示一种魔板状态,规定从魔板的左上角开始,沿顺时针方向依次取出整数,构成一个颜色序列。

对于上图的魔板状态,我们用序列(1,2,3,4,5,6,7,8)来表示。

这是基本状态。

这里提供三种基本操作,分别用大写字母“A”,“B”,“C”来表示(可以通过这些操作改变魔板的状态):

“A”:交换上下两行;

“B”:将最右边的一列插入最左边;

“C”:魔板中央四格作顺时针旋转。

下面是对基本状态进行操作的示范:

A: 8 7 6 5

1 2 3 4

B: 4 1 2 3

5 8 7 6

C: 1 7 2 4

8 6 3 5

对于每种可能的状态,这三种基本操作都可以使用。

你要编程计算用最少的基本操作完成基本状态到目标状态的转换,输出基本操作序列。

输入格式

只有一行,包括8个整数,用空格分开(这些整数在范围 1——8 之间)不换行,表示目标状态。

输出格式

Line 1: 包括一个整数,表示最短操作序列的长度。

Line 2: 在字典序中最早出现的操作序列,用字符串表示,除最后一行外,每行输出60个字符。

输入样例
2 6 8 4 5 7 3 1
输出样例
7
BCABCCB
说明

选自USACO Training Section 3.2

做完八数码问题,不难理解这道题可以使用广搜解决(毕竟时间复杂度与八数码问题类似)。

像之前的八数码问题一样,我们把状态定义成一个八位数,代码中简单的使用STL中map和set进行记录与判重。

留意:本题有一个陷肼,如果使用从上到下、从左向右进行加和操作确定状态时,初状态应为:12348765!

代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#include<set>
using namespace std;
const int rot[4] = {2, 1, 5, 6};
int st = 12348765, ed = 0, s[10];
map <int, int> d, f;
set <int> vis;
void decode(int state, int *p)
{
for(int i = 7; i >= 0; -- i)
{
p[i] = state % 10;
state /= 10;
}
//将十进制编码转化为数组
return;
}
int encode(int *p)
{
int cnt = 0;
for(int i = 0; i < 8; ++ i)
{
cnt = (cnt << 1) + (cnt << 3) + p[i];
}
//将数组转化为十进制8位编码
return cnt;
}
void flip(int cur, int *p)
{
switch(cur)
{
case 0 :
{
for(int i = 0; i < 4; ++ i)
{
swap(p[i], p[i + 4]);
}
break;
}
case 1 :
{
for(int i = 2; i > -1; -- i)
{
swap(p[i], p[i + 1]);
swap(p[i + 4], p[i + 5]);
}
break;
}
case 2 :
{
for(int i = 0; i < 3; ++ i)
{
swap(p[rot[i]], p[rot[i + 1]]);
}
break;
}
}
return;
}
void print_ans(int state)
{
if(state == st) return;
int prev_state = 0;
decode(state, s);
switch(f[state])
{
case 0:
{
for(int i = 0; i < 4; ++ i)
{
swap(s[i], s[i + 4]);
}
break;
}
case 1:
{
for(int i = 0; i < 3; ++ i)
{
swap(s[i], s[i + 1]);
swap(s[i + 4], s[i + 5]);
}
break;
}
case 2:
{
for(int i = 2; i >= 0; -- i)
{
swap(s[rot[i + 1]], s[rot[i]]);
}
break;
}
}
for(int i = 0; i < 8; ++ i)
{
prev_state = prev_state * 10 + s[i];
}
memset(s, 0, sizeof(s));
print_ans(prev_state);
printf("%c", f[state] + 'A');
return;
}
void bfs()
{
//特判 初始状态 和 目标状态 相同
if(st == ed) {
puts("0");
return;
} f.clear(), vis.clear();
queue <int> Q;
while(!Q.empty()) Q.pop(); Q.push(st);
vis.insert(st);
int copy[8] = {}, now, next; while(!Q.empty())
{
now = Q.front();
Q.pop();
decode(now, s);
memcpy(copy, s, sizeof(copy));
for(int i = 0; i < 3; ++ i)
{
flip(i, s);
next = encode(s);
memcpy(s, copy, sizeof(s)); if(vis.count(next)) continue;
d[next] = d[now] + 1;
f[next] = i;
if(next == ed)
{
printf("%d\n", d[next]);
print_ans(next);
return;
}
Q.push(next);
vis.insert(next);
}
}
return;
}
int main()
{
memset(s, 0, sizeof(s));
for(int i = 0; i < 4; ++ i) scanf("%d", &s[i]);
//目标状态处理:
for(int i = 7; i >= 4; -- i) scanf("%d", &s[i]);
//留意陷阱呢
for(int i = 0; i < 8; ++ i)
{
ed = (ed << 1) + (ed << 3) + s[i];
}
bfs();
return 0;
}

[USACO3.2]魔板 Magic Squares的更多相关文章

  1. 「一本通 1.4 例 2」[USACO3.2]魔板 Magic Squares

    [USACO3.2]魔板 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. 哈希+Bfs【P2730】 魔板 Magic Squares

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

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

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

  5. 洛谷 P2730 魔板 Magic Squares

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

  6. [洛谷P2730] 魔板 Magic Squares

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

  7. 魔板 Magic Squares(广搜,状态转化)

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

  8. P2730 魔板 Magic Squares

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

  9. 洛谷P2730 [IOI]魔板 Magic Squares

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

随机推荐

  1. NKOJ4270 小奇挖矿2

    问题描述 [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿石交易市场,以便为飞船升级无限非概率引擎. [问题描述] 现在有m+1个星球,从左到右标号为0到m,小 ...

  2. STM32F103ZET6 PWM输出

    1.通用定时器的PWM功能 STM32F103ZET6有4个通用定时器,分别是TIM2.TIM3.TIM4.TIM5. 通用定时器由一个可编程预分频器驱动的16位自动装载计数器构成. 通用定时器的很多 ...

  3. PTA数据结构与算法题目集(中文) 7-19

    PTA数据结构与算法题目集(中文)  7-19 7-19 求链式线性表的倒数第K项 (20 分)   给定一系列正整数,请设计一个尽可能高效的算法,查找倒数第K个位置上的数字. 输入格式: 输入首先给 ...

  4. .NET Core项目部署到Linux(Centos7)(六)发布.NET Core 项目到Linux

    目录 1.前言 2.环境和软件的准备 3.创建.NET Core API项目 4.VMware Workstation虚拟机及Centos 7安装 5.Centos 7安装.NET Core环境 6. ...

  5. docker+nginx 微信支付回调

    制作微信支付发现回调有问题: docker-compose中接口要映射对应地址 然后再进行访问

  6. 2017蓝桥杯最大公共子串(C++B组)

    题目: 最大公共子串长度问题就是:求两个串的所有子串中能够匹配上的最大长度是多少.比如:"abcdkkk" 和 "baabcdadabc",可以找到的最长的公共 ...

  7. split(resource,limit) 中limit 的含义

    limit 参数控制模式应用的次数,因此影响结果数组的长度.如果该限制 n 大于 0,则模式将被最多应用 n - 1 次,数组的长度将不会大于 n,而且数组的最后项将包含超出最后匹配的定界符的所有输入 ...

  8. [总结]RMQ问题&ST算法

    目录 一.ST算法 二.ST算法の具体实现 1. 初始化 2. 求出ST表 3. 询问 三.例题 例1:P3865 [模板]ST表 例2:P2880 [USACO07JAN]平衡的阵容Balanced ...

  9. 天天在用Redis,持久化方案你又知道哪些?

    前言 文章首发于微信公众号[码猿技术专栏]:天天用Redis,持久化方案有哪些你知道吗? Redis目前已经成为主流的内存数据库了,但是大部分人仅仅是停留在会用的阶段,你真的了解Redis内部的工作原 ...

  10. 学习Salesforce | Einstein业务机会评分怎么玩

    Einstein 业务机会评分(Opportunity Scoring)是销售团队的得力助手,通过分数以及研究影响分数的因素,确定业务机会的优先级,赢得更多交易. Einstein 业务机会评分可以给 ...