题目描述
X星球的流行宠物是青蛙,一般有两种颜色:白色和黑色。
X星球的居民喜欢把它们放在一排茶杯里,这样可以观察它们跳来跳去。
如下图,有一排杯子,左边的一个是空着的,右边的杯子,每个里边有一只青蛙。
*WWWBBB
其中,W字母表示白色青蛙,B表示黑色青蛙,*表示空杯子。
X星的青蛙很有些癖好,它们只做3个动作之一:
1. 跳到相邻的空杯子里。
2. 隔着1只其它的青蛙(随便什么颜色)跳到空杯子里。
3. 隔着2只其它的青蛙(随便什么颜色)跳到空杯子里。
对于上图的局面,只要1步,就可跳成下图局面:
WWW*BBB
本题的任务就是已知初始局面,询问至少需要几步,才能跳成另一个目标局面。
数据规模和约定
我们约定,输入的串的长度不超过15
输入
输入为2行,2个串,表示初始局面和目标局面。
输出
输出要求为一个整数,表示至少需要多少步的青蛙跳。
样例输入
∗
*
∗WWBB
WWBB
∗
*
∗
样例输入
WWW
∗
*
∗BBB
BBB
∗
*
∗WWW
样例输出
样例输出
2
样例输出
10
老师让我验题,我就写了一下,用了状压的骚操作,不过不用状压也可以做。
对涉及每种状态的存储,就三进制压缩存咯,涉及到解码和译码的概念,写起来也是比较简单
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
using namespace std;
int star=0,tar=0;
char str[20];
int len;
set<int> _set;
struct node
{
int num;
int step;
node(int _num,int _step):num(_num),step(_step){}
};
int c[20];
int encode()
{
int ans=0;
for(int i=0;i<len;i++)
ans=ans*3+c[i];
return ans;
}
int em;
void decode(int num)
{
for(int i=len-1;i>=0;i--)
{
c[i]=num%3;
if(!c[i])em=i;
num/=3;
}
}
int main()
{
scanf("%s",str);
len=strlen(str);
for(int i=0;i<len;i++)
{
if(str[i]=='W')star=star*3+1;
else if(str[i]=='B')star=star*3+2;
else star=star*3;
}
scanf("%s",str);
for(int i=0;i<len;i++)
{
if(str[i]=='W')tar=tar*3+1;
else if(str[i]=='B')tar=tar*3+2;
else tar=tar*3;
}
/*cout<<tar<<endl;
for(int i=0;i<len;i++)
cout<<c[i];
cout<<endl;*/
queue<node>que;
int ans;
que.push(node(star,0));
while(que.size())
{
node now=que.front();que.pop();
if(now.num==tar)
{
ans=now.step;
break;
}
int st;
decode(now.num);
for(int i=-3;i<=3;i++)
{
if(em+i>=0&&em+i<len&&i!=0)
{
swap(c[em],c[em+i]);
st=encode();
if(_set.find(st)==_set.end())
{
que.push(node(st,now.step+1));
_set.insert(st);
}
swap(c[em],c[em+i]);
}
}
}
cout<<ans<<endl;
return 0;
}