题意:
给你一个字符串,长度是5,每一个字母都是‘0’到‘9’,将它转换成给出的字符串最少多少步。
操作如下:
1、交换任意相邻的两个数,无次数限制
2、任意一位上的数字加1,超过10对10取模,限制3次。
3、任意一位上的数字*2,超过10对10取模,限制2次。
分析:
就是bfs暴力打表,将12345转化成的10^5种可能的结果都处理出来
代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
int n,m,k;
int go;
int vis[100010][4][3];
bool us[100010];
int jc[10];
void bfs()
{
memset(us,0,sizeof(us));
jc[6]=1;
for(int i=5;i>=0;i--)
jc[i]=jc[i+1]*10;
for(int i=0;i<=99999;i++)
for(int j=0;j<4;j++)
for(int k=0;k<3;k++)
vis[i][j][k]=inf;
queue<int>q;
q.push(12345);
us[12345]=1;
vis[12345][0][0]=0;
while(!q.empty())
{
int a=q.front();q.pop();
us[a]=0;
///交换
for(int i=1;i<5;i++)
{
int j=i+1;
int x=(a%jc[i])/jc[i+1];
int y=(a%jc[j])/jc[j+1];
if(x==y) continue;
int tmp=a-x*jc[i+1]-y*jc[j+1];
tmp+=x*jc[j+1]+y*jc[i+1];
int fg=0;
for(int k=0;k<4;k++)
for(int l=0;l<3;l++)
{
if(vis[tmp][k][l]>vis[a][k][l]+1)
{
vis[tmp][k][l]=vis[a][k][l]+1;
fg=1;
}
}
if(fg&&!us[tmp]) {
us[tmp]=1;
q.push(tmp);
}
}
///加1
for(int i=1;i<6;i++)
{
int x=(a%jc[i])/jc[i+1];
int tmp=a-x*jc[i+1]+((x+1)%10)*jc[i+1];
if(tmp==a) continue;
int fg=0;
for(int k=1;k<4;k++)
for(int l=0;l<3;l++)
if(vis[tmp][k][l]>vis[a][k-1][l]+1)
{
vis[tmp][k][l]=vis[a][k-1][l]+1;
fg=1;
}
if(fg&&!us[tmp]) {
us[tmp]=1;
q.push(tmp);
}
}
///加倍
for(int i=1;i<6;i++)
{
int x=(a%jc[i])/jc[i+1];
int tmp=a-x*jc[i+1]+((x*2)%10)*jc[i+1];
if(tmp==a) continue;
int fg=0;
for(int k=0;k<4;k++)
for(int l=1;l<3;l++)
if(vis[tmp][k][l]>vis[a][k][l-1]+1)
{
vis[tmp][k][l]=vis[a][k][l-1]+1;
fg=1;
}
if(fg&&!us[tmp]) {
us[tmp]=1;
q.push(tmp);
}
}
}
}
int main()
{
bfs();
int x;
while(scanf("%d",&x)!=EOF)
{
int ma=inf;
for(int i=0;i<4;i++)
for(int j=0;j<3;j++)
ma=min(ma,vis[x][i][j]);
if(ma==inf) puts("-1");
else printf("%d\n",ma);
}
return 0;
}