1107. 魔板
题意:
tips
字典序不会为难你,只是出题人方便评测而已
区别(和最短路的区别)
这是状态到状态的最小步数,
而不是某点到某点的 最下步数
存状态
一般用hash来存状态
使用map 进行hash (map和under_map不差)
(这题也可以用康托展开)
字典序的处理
证明难度异常Emm,结论如此简单
我们处理的时候
只需要先A再B然后C的顺序
那么一定可以得到最小字典序
code(含注释):
#include <bits/stdc++.h>
using namespace std;
char g[2][4];///用来存储魔方
struct node
{
char x;
string y;
};
unordered_map<string,node> pre;
unordered_map<string,int> dist;
void set1(string state)
{
for(int i=0;i<4;i++)
g[0][i] = state[i];
for(int i = 7,j=0;j<4;i--,j++)
g[1][j] = state[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 state)
{
set1(state);
for(int i=0;i<4;i++)
swap(g[0][i],g[1][i]);
return get();
}
string move1(string state)
{
set1(state);
int v0 =g[0][3];///记录最后一列
int 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 state)
{
set1(state);
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 st,string ed)
{
if(st == ed)
return 0;///如果是直接相等的
queue<string> q;
q.push(st);
dist[st] = 0 ;
while(!q.empty())
{
string 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;
pre[m[i]] ={'A'+i,t};///存的是操作数ABC 和 之前的状态
q.push(m[i]);
if(m[i] == ed)
return dist[ed];
}
// cout<<"error"<<endl;
}
}
return -1;
}
int main()
{
int x;
string st,ed;
for(int i=0; i<8; i++)
{
cin>>x;
ed+=char(x+'0');
///666 原来可以这样子int 转换成 char
}
for(int i =1; i<=8; i++)
st+=char('0'+i);
int step = bfs(st,ed);///bfs跑最短
cout<<step<<endl;
string res;
while(ed!=st)
{
res+= pre[ed].x;
ed= pre[ed].y;
}
reverse(res.begin(),res.end());
///因为是从 终点跑起点所以是要反转吗
if(step>0)
cout<<res<<endl;
return 0;
}