原文链接:http://acm.hdu.edu.cn/showproblem.php?pid=1430
思路:
题目说求出最少的变换步骤,那么首选BFS搜索,看了网上一些人写的用的多是康托展开,但感觉这里不必用康托展开就行,但BFS预处理还是必须的。这是因为BFS作为广度搜索如果我们对于每个测试用例都去用一遍BFS的话,很有可能出现TLE,所以在BFS中常用的是BFS预处理,即一开始就把所有情况搜索出来,然后对于多种测试用例,调取预处理后的结果输出即可。
这道题在这里有个思路,就是再进行BFS预处理之后,我们需要把所有的初始状态到最终状态映射成“12345678”到相对应的结果状态,通过这个思路找到对应的步骤方式。是一道有难度的BFS搜索问题
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<map>
using namespace std;
string st,ed;
map<string,string>mapp;
map<string,string>::iterator it;
struct magic
{
string str;//记录各种状态
string alp;//记录操作字符
};
string a(string x)//a变换
{
string ans="";
for(int i=x.size()-1;i>=0;i--)
{
ans+=x[i];
}
return ans;
}
string b(string x)//b变换
{
string ans="";
ans+=x[3];ans+=x[0];ans+=x[1];ans+=x[2];ans+=x[5];ans+=x[6];ans+=x[7];ans+=x[4];
//执行b变换的操作
return ans;
}
string c(string x)//c变换
{
string ans="";
ans+=x[0];ans+=x[6];ans+=x[1];ans+=x[3];ans+=x[4];ans+=x[2];ans+=x[5];ans+=x[7];
return ans;
}
void BFS()//预处理所有的变换情况
{
magic now,next;
now.str="12345678";
now.alp="";
queue<magic>q;
q.push(now);
while(!q.empty())
{
now=q.front();
q.pop();
it=mapp.find(now.str);
if(it!=mapp.end())//为了让字典序最小,删掉已经找到的路
continue;
mapp[now.str]=now.alp;//存储不同状态
next.str=a(now.str);next.alp=now.alp+'A';
q.push(next);
next.str=b(now.str);next.alp=now.alp+'B';
q.push(next);
next.str=c(now.str);next.alp=now.alp+'C';
q.push(next);
}
}
//这里有个思路,就是再进行BFS预处理之后,我们需要把所有的初始状态到最终状态映射成“12345678”到相对应的结果状态,通过这个思路找到对应的步骤方式
int main()
{
BFS();
while(cin>>st>>ed)
{
string ans="";
for(int i=0;i<8;i++)
{
for(int j=0;j<8;j++)//找到变换前后对应的位置
{
if(ed[i]==st[j])//通过累加每一位不同的值,得到一个数用于代表不同的状态
ans+=j+'0'+1;//这里注意是通过结果找到从原来的位置移动到结果位置所移动的位置数
}
}
cout<<mapp[ans]<<endl;//找到相对应的移动的方式
}
return 0;
}