魔板-------------------------------最小步数模型

魔板-------------------------------最小步数模型Rubik 先生在发明了风靡全球的魔方之后 又发明了它的二维版本 魔板

Rubik 先生在发明了风靡全球的魔方之后,又发明了它的二维版本——魔板。

这是一张有 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:魔板中央对的4个数作顺时针旋转。

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

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 个整数,用空格分开,表示目标状态。

输出格式
输出文件的第一行包括一个整数,表示最短操作序列的长度。

如果操作序列的长度大于0,则在第二行输出字典序最小的操作序列。

数据范围
输入数据中的所有数字均为 1 到 8 之间的整数。

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

解析:
这种题目很简单,但是对码代码能力很考验。
因为有三种变换,且必须字典序最小输出。所以我们要按照A,B,C这三个操作顺序放到队列里面去。如果队列已经存在了,那就不放。还需要记录一下前驱

#include<bits/stdc++.h> using namespace std; char g[2][4]; unordered_map<string, pair<char, string>> pre;//记录前驱+答案 unordered_map<string, int> dist; //记录距离 int x; void set1(string t) { 
    for(int i=0;i<4;i++) g[0][i]=t[i]; for(int i=7,j=0;j<4;j++,i--) g[1][j]=t[i]; } string get() { 
    string res; for(int i=0;i<4;i++) res+=g[0][i]; for(int i=3;i>=0;i--) res+=g[1][i]; return res; } string move0(string t) { 
    set1(t); for(int i=0;i<4;i++) swap(g[0][i],g[1][i]); return get(); } string move1(string t) { 
    set1(t); int v0 = g[0][3], v1 = g[1][3]; for (int i = 3; i >= 0; i -- ) { 
    g[0][i] = g[0][i - 1]; g[1][i] = g[1][i - 1]; } g[0][0] = v0, g[1][0] = v1; return get(); } string move2(string t) { 
    set1(t); int v = g[0][1]; g[0][1] = g[1][1]; g[1][1] = g[1][2]; g[1][2] = g[0][2]; g[0][2] = v; return get(); } int bfs(string start,string end) { 
    if(start==end) return 0; //如果一开始就相等,返回0 queue<string > q; q.push(start);//一开始的状态放入到队列 dist[start]=0;//初始化距离 while(q.size()) { 
    auto t=q.front(); q.pop(); string m[3]; m[0]=move0(t);//三种状态转移 m[1]=move1(t); m[2]=move2(t); for(int i=0;i<3;i++)//判断三种状态之前有没有出现过 { 
    if(!dist.count(m[i]))//没出现过 { 
    dist[m[i]]=dist[t]+1;//步数+1 pre[m[i]]={ 
   'A'+i,t}; q.push(m[i]);//入队 if(m[i]==end) return dist[end];//正好等于最终状态返回。 } } } return -1; } int main() { 
    string start,end; for(int i=0;i<8;i++) { 
    cin>>x; end+=char(x+'0'); } for(int i=0;i<8;i++) start+=char(i+'1'); int k=bfs(start,end); cout<<k<<endl; string res; while(end!=start) { 
    res+=pre[end].first; end=pre[end].second; } reverse(res.begin(),res.end()); if(k>0) cout<<res<<endl; } 
今天的文章 魔板-------------------------------最小步数模型分享到此就结束了,感谢您的阅读。
编程小号
上一篇 2024-12-10 07:30
下一篇 2024-12-10 07:27

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/82881.html