题意:给你长度为110以内的,由1~6的数字构成的字符串,求从start串到end串的最小操作次数,每次操作可以:
①将一个位置的字符,替换成一个字符。
②将一种类型的字符,替换成另一种类型。
题解:首先我们可以考虑,第一种操作肯定在第二种操作之后,假如我们先替换单个字符1为2,再将所有的替换为3,那么还不如直接先将所有的替换为3,再将1替换为3。所以可以知道,第二种操作是可以在第一种操作之前的,所以我们先预处理,第二种操作的转移到的所有情况的最小操作次数。然后考虑转移之后的单步需要的次数。
AC代码:
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
char s[115],e[115];
int dp[600005];
int state[15];
int zy[15][15];
void init()
{
int sum=0;
for(int i=5;i>=0;i--)
sum=sum*6+i;
queue<int>que;
que.push(sum);
dp[sum]=0;
while(!que.empty())
{
int k=que.front();
que.pop();
for(int i=0;i<6;i++)
for(int j=0;j<6;j++)
{
if(i==j)continue;
int now=k;
for(int g=0;g<6;g++)
state[g]=now%6,now/=6;
sum=0;
for(int g=5;g>=0;g--)
{
if(state[g]==i)
state[g]=j;
sum=sum*6+state[g];
}
if(dp[sum]!=-1)continue;
dp[sum]=dp[k]+1;
que.push(sum);
}
}
}
int main()
{
memset(dp,-1,sizeof(dp));
init();
while(~scanf("%s%s",e,s))
{
memset(zy,0,sizeof(zy));
int l=strlen(s);
for(int i=0;i<l;i++)
zy[s[i]-'1'][e[i]-'1']++;
int ans=10000;
for(int i=0;i<600000;i++)
{
if(dp[i]==-1)continue;
int sum=0,k=i;
for(int j=0;j<6;j++)
{
int now=k%6;k/=6;
sum+=zy[j][now];
}
ans=min(ans,l-sum+dp[i]);
}
printf("%d\n",ans);
}
}