题目大意:给定一个5位数,可以进行一下变换:
①任选两个位进行交换(不限次数);
②任选一位进行加一,如果超过10则模除10(仅限三次);
③任选一位乘以2,如果超过10则模除10(仅限2次);
问这个五位数经过最少多少次变换能够成为12345;
如果可以,输出最小次数,否则输出-1;
解: 用bfs,模拟出所有的12345变换情况,开个三维数组 m[x][y][z] ,表示12345变换成x,②用了y次,③用了z次时的最少步数;
#include <iostream>
#include <queue>
#include <algorithm>
#include <string.h>
#include <string>
using namespace std;
struct pt{
string s;
int step1;
int step2;
int step;
};
bool operator <(pt a,pt b)
{
return a.step>b.step;
}
pt st;
int mi=0x3f3f3f3f;
int m[100000][5][5];
int change(string s)
{
int sum;
sum=s[0]-48;
for (int i=1;i<5;i++)
sum=sum*10+s[i]-48;
return sum;
}
void bfs()
{
priority_queue<pt>q;
pt p,pp;
int nu;
q.push(st);
while (!q.empty())
{
pp=q.top();
q.pop();
p.step=pp.step+1;
for (int i=0;i<4;i++)
{
p.step1=pp.step1;
p.step2=pp.step2;
p.s=pp.s;
swap(p.s[i],p.s[i+1]);
nu=change(p.s);
if (m[nu][p.step1][p.step2]!=mi)continue;
m[nu][p.step1][p.step2]=p.step;
q.push(p);
}
if (pp.step1<3)
{
for (int i=0;i<5;i++)
{
p.s=pp.s;
p.s[i]=((pp.s[i]-48)+1)%10+48;
p.step1=pp.step1+1;
p.step2=pp.step2;
nu=change(p.s);
if (m[nu][p.step1][p.step2]!=mi)continue;
m[nu][p.step1][p.step2]=p.step;
q.push(p);
}
}
if (pp.step2<2)
{
for (int i=0;i<5;i++)
{
p.s=pp.s;
p.s[i]=((pp.s[i]-48)*2)%10+48;
p.step1=pp.step1;
p.step2=pp.step2+1;
nu=change(p.s);
if (m[nu][p.step1][p.step2]!=mi)continue;
m[nu][p.step1][p.step2]=p.step;
q.push(p);
}
}
}
}
int main()
{
st.step1=st.step2=st.step=0;
st.s="12345";
memset(m,0x3f3f3f3f,sizeof(m));
m[12345][0][0]=0;
bfs();
string ss;
while (cin>>ss)
{
int minn=0x3f3f3f3f;
for (int i=0;i<=3;i++)
for (int j=0;j<=2;j++)
minn=min(minn,m[change(ss)][i][j]);
printf("%d\n",minn==0x3f3f3f3f?-1:minn);
}
return 0;
}