【BFS】魔板(c++基础算法)

简介: 【BFS】魔板(c++基础算法)

 本专栏上一篇:【BFS】八数码问题(c++基础算法)


目录

一.读题

①题面

②题意

三.做题

①算法原理

②算法实现

Ⅰ三种基本操作

Ⅱ操作序列

Ⅲ输出

Ⅳ一个特殊情况

四.AC代码

最后


一.读题

①题面

【宽搜(难度:6)】魔板

【题目描述】

在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板。

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

正在上传…重新上传取消

我们知道魔板的每一个方格都有一种颜色。这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 之间),表示目标状态。

【输出格式】

第一行包括一个整数,表示最短操作序列的长度。

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

【样例输入】

2 6 8 4 5 7 3 1

【样例输出】

7

BCABCCB

②题意

很显然,这道题是让我们求12345678经过三种变化,到目标状态 的步数与变化操作。


三.做题

①算法原理

这题与【BFS】八数码问题极其相似,我就在讲论两者间的区别中,来把这题讲给你。

②算法实现

Ⅰ三种基本操作

相对于八数码的空格上下左右操作,这题有三种不同的操作。

“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

看到很多人都是用二维数组来搞,但我觉得没有必要。我直接在main函数中,利用switch()语句来进行。

“A”功能:循环j从1-4,交换a[j] 与a[9-j]。

“B”功能:循环j从1-3,交换a[j],a[4],和a[9-j],a[5].(不断对第j列[j会不断加1]和最后一列交换,最终达成目的)

“C”功能,直接换来换去。

switch(i)
      {
        case 1:
          for(int i=1;i<=4;i++)
          {
            swap(ne.a[i],ne.a[9-i]);
          }
          break;
        case 2: 
          for(int i=1;i<=3;i++)
          {
            swap(ne.a[i],ne.a[4]);
            swap(ne.a[9-i],ne.a[5]);
          }
          break;
        case 3: 
          swap(ne.a[3],ne.a[6]);
          swap(ne.a[7],ne.a[3]);
          swap(ne.a[3],ne.a[2]);
      }

image.gif

Ⅱ操作序列

我将每钟情况都赋予一个序列。当此情况可行(之前没出现过),先将其上一步序列赋值到它身上,在增加此次操作的序列。

for(int k=1;k<=q.front().ans;k++) ne.bz[k]=q.front().bz[k];
  ne.bz[ne.ans]=i;

image.gif

Ⅲ输出

先将操作次数输出,再对序列操作,然后输出。

对序列的操作:原有基础上,强制转换为字符,加上‘A’,减一(因为序列数为1时应输出A,而不建议会变为B,因此要减一)

if(ne.kt==ed.kt)
   {
       printf("%d\n",q.back().ans);
       for(int k=1;k<=q.back().ans;k++) printf("%c",q.back().bz[k]+'A'-1);
       exit(0); 
    }

image.gif

Ⅳ一个特殊情况

当目标状态与初始状态一样时,会无法进入我的输出语句。因此要在结尾输出一个0(因为当出现上述情况时,无需操作即可达到目标状态)


四.AC代码

不写注释啦!

#include<bits/stdc++.h>
using namespace std;
struct node{
  int kt,ans,bz[1005];
  int a[10];
}st,ed;
bool b[50000];
queue<node>q;
long kt(node t)
{
  long long s=1;
  for(int i=1;i<=8;i++)
  {
    int index=1,f=1,count=0;
    for(int j=i+1;j<=8;j++)
    {
      if(t.a[i]>t.a[j]) count++;
      f*=index++;
    }
    s=s+f*count;
  }
  return s;
}
int main()
{
  for(int i=1;i<=8;i++) st.a[i]=i;
  st.kt=kt(st);
  b[st.kt]=1;
  for(int i=1;i<=8;i++) scanf("%d",&ed.a[i]);
  ed.kt=kt(ed);
  q.push(st);
  while(!q.empty())
  {
    for(int i=1;i<=3;i++)
    {
      node ne=q.front();
      switch(i)
      {
        case 1:
          for(int i=1;i<=4;i++)
          {
            swap(ne.a[i],ne.a[9-i]);
          }
          break;
        case 2: 
          for(int i=1;i<=3;i++)
          {
            swap(ne.a[i],ne.a[4]);
            swap(ne.a[9-i],ne.a[5]);
          }
          break;
        case 3: 
          swap(ne.a[3],ne.a[6]);
          swap(ne.a[7],ne.a[3]);
          swap(ne.a[3],ne.a[2]);
      }
      ne.ans++;
      ne.kt=kt(ne);
      if(!b[ne.kt])
      {
        for(int k=1;k<=q.front().ans;k++) ne.bz[k]=q.front().bz[k];
        ne.bz[ne.ans]=i;
        b[ne.kt]=1;
        q.push(ne); 
        if(ne.kt==ed.kt)
                {
                  printf("%d\n",q.back().ans);
                  for(int k=1;k<=q.back().ans;k++) printf("%c",q.back().bz[k]+'A'-1);
                  exit(0); 
            }
      }
    }
    q.pop();
  }
  printf("0"); 
}

image.gif


最后

我是在网课期间摸鱼写作的,很辛苦。给个红心不过分吧。。。

相关文章
|
2天前
|
负载均衡 算法 安全
探秘:基于 C++ 的局域网电脑控制软件自适应指令分发算法
在现代企业信息化架构中,局域网电脑控制软件如同“指挥官”,通过自适应指令分发算法动态调整指令发送节奏与数据量,确保不同性能的终端设备高效运行。基于C++语言,利用套接字实现稳定连接和线程同步管理,结合实时状态反馈,优化指令分发策略,提升整体管控效率,保障网络稳定,助力数字化办公。
37 19
|
7天前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
28 2
|
15天前
|
存储 算法 安全
基于红黑树的局域网上网行为控制C++ 算法解析
在当今网络环境中,局域网上网行为控制对企业和学校至关重要。本文探讨了一种基于红黑树数据结构的高效算法,用于管理用户的上网行为,如IP地址、上网时长、访问网站类别和流量使用情况。通过红黑树的自平衡特性,确保了高效的查找、插入和删除操作。文中提供了C++代码示例,展示了如何实现该算法,并强调其在网络管理中的应用价值。
|
13天前
|
存储 算法 安全
基于哈希表的文件共享平台 C++ 算法实现与分析
在数字化时代,文件共享平台不可或缺。本文探讨哈希表在文件共享中的应用,包括原理、优势及C++实现。哈希表通过键值对快速访问文件元数据(如文件名、大小、位置等),查找时间复杂度为O(1),显著提升查找速度和用户体验。代码示例展示了文件上传和搜索功能,实际应用中需解决哈希冲突、动态扩容和线程安全等问题,以优化性能。
|
20天前
|
算法 安全 C++
用 C++ 算法控制员工上网的软件,关键逻辑是啥?来深度解读下
在企业信息化管理中,控制员工上网的软件成为保障网络秩序与提升办公效率的关键工具。该软件基于C++语言,融合红黑树、令牌桶和滑动窗口等算法,实现网址精准过滤、流量均衡分配及异常连接监测。通过高效的数据结构与算法设计,确保企业网络资源优化配置与安全防护升级,同时尊重员工权益,助力企业数字化发展。
39 4
|
4月前
|
存储 算法 安全
超级好用的C++实用库之sha256算法
超级好用的C++实用库之sha256算法
178 1
|
3月前
|
算法 数据处理 C++
c++ STL划分算法;partition()、partition_copy()、stable_partition()、partition_point()详解
这些算法是C++ STL中处理和组织数据的强大工具,能够高效地实现复杂的数据处理逻辑。理解它们的差异和应用场景,将有助于编写更加高效和清晰的C++代码。
62 0
|
3月前
|
存储 算法 程序员
迪杰斯特拉(Dijkstra)算法(C/C++)
迪杰斯特拉(Dijkstra)算法(C/C++)
|
3月前
|
机器学习/深度学习 存储 算法
数据结构与算法——BFS(广度优先搜索)
数据结构与算法——BFS(广度优先搜索)
|
3月前
|
人工智能 算法 Java
【搜索算法】数字游戏(C/C++)
【搜索算法】数字游戏(C/C++)

热门文章

最新文章