题意:给你两个只由1~6组成的串,问你B串至少要经过几次操作变成A串。
一次操作要么选择一个种类的数,将其全部变成另一种类;要么选择一个数,将其变为另一个数。
可以证明,一定先进行一定数量的第一种操作,然后再进行一定数量的第二种操作。
所以可以BFS预处理序列每种数要变成哪种数所需要的代价。初始状态是123456,代表1->1,2->2,...,6->6,一共才6^6种状态。
然后再枚举一遍所有状态,把该种状态下,剩下的仍然不符的数强行变过去就行了,然后在所有答案中取个最小的。
#include<cstdio> #include<queue> #include<cstring> using namespace std; int d[700000]; bool vis[700000]; int n,pw[10]; queue<int>q; char s[125],s2[125]; int main(){ // freopen("c.in","r",stdin); memset(d,0x7f,sizeof(d)); pw[0]=1; for(int i=1;i<=6;++i){ pw[i]=pw[i-1]*10; } q.push(123456); vis[123456]=1; d[123456]=0; int t[7]; while(!q.empty()){ bool used[7]={0}; int U=q.front(); q.pop(); for(int i=1;i<=6;++i){ if(!used[i]){ int e=0; int wei=U/pw[i-1]%10; for(int j=i;j<=6;++j){ if(wei==U/pw[j-1]%10){ used[j]=1; t[++e]=j; } } for(int j=1;j<=6;++j){ if(j!=wei){ int tmp=U; for(int k=1;k<=e;++k){ tmp+=(j-wei)*pw[t[k]-1]; } if(!vis[tmp]){ vis[tmp]=1; d[tmp]=d[U]+1; q.push(tmp); } } } } } } while(scanf("%s%s",s2+1,s+1)!=EOF){ int ans=2147483647; n=strlen(s+1); for(int i=1;i<=6;++i){ for(int j=1;j<=6;++j){ for(int k=1;k<=6;++k){ for(int l=1;l<=6;++l){ for(int p=1;p<=6;++p){ for(int q=1;q<=6;++q){ int x=i*100000+j*10000+k*1000+l*100+p*10+q; if(d[x]<2000000000){ int cnt=0; for(int pp=1;pp<=n;++pp){ int tt; if(s[pp]=='1'){ tt=i; } else if(s[pp]=='2'){ tt=j; } else if(s[pp]=='3'){ tt=k; } else if(s[pp]=='4'){ tt=l; } else if(s[pp]=='5'){ tt=p; } else{ tt=q; } if(tt+'0'!=s2[pp]){ ++cnt; } } ans=min(ans,cnt+d[x]); } } } } } } } printf("%d\n",ans); } return 0; }