# HDOJ4433-locker,2012ACM天津站C题,DP

dp[i][j]表示前i个数字中前i-2个数字已经调换好了，第i-1个数字x和第i个数字y满足x*10+y=j对应状态的最小操作数,代码如下：

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

const int NN=1010;

int r1[NN][NN],r2[NN][NN],r3[NN][NN];

int min3(int x,int y,int z)
{
int ret=x;
if (y<ret) ret=y;
if (z<ret) ret=z;
return ret;
}

int fuck1(int x,int y)//一位数转变
{
if (r1[x][y]!=-1) return r1[x][y];
if (x==y) return r1[x][y]=0;

if (x>y) return r1[x][y]=r1[y][x]=min(x-y,10+y-x);
else     return r1[y][x]=r2[x][y]=min(y-x,10+x-y);
}

int fuck2(int x,int y)//两位数转变
{
if (r2[x][y]!=-1) return r2[x][y];
if (x==y) return r2[x][y]=0;

int a,b,tmp;
int ret=fuck1(x/10,y/10)+fuck1(x%10,y%10);
a=x;
for (int i=1; i<=5; i++)
{
b=0;
for (int k=1; k<=10; k*=10) if (a/k%10<9) b+=((a/k%10)+1)*k;
a=b;
tmp=fuck1(a/10,y/10)+fuck1(a%10,y%10);
if (tmp+i<ret) ret=tmp+i;
}
for (int i=4; i>=1; i--)
{
b=0;
for (int k=1; k<=10; k*=10) if (a/k%10<9) b+=((a/k%10)+1)*k;
a=b;
tmp=fuck1(a/10,y/10)+fuck1(a%10,y%10);
if (tmp+i<ret) ret=tmp+i;
}
return r2[x][y]=r2[y][x]=ret;
}

int fuck3(int x,int y)//三位一起转变
{
if (r3[x][y]!=-1) return r3[x][y];
if (x==y) return r3[x][y]=0;

int a,b,tmp;
int ret=min(fuck1(x/100,y/100)+fuck2(x%100,y%100),fuck2(x/10,y/10)+fuck1(x%10,y%10));
a=x;
for (int i=1; i<=5; i++)
{
b=0;
for (int k=1; k<=100; k*=10) if (a/k%10<9) b+=((a/k%10)+1)*k;
a=b;
tmp=min(fuck1(a/100,y/100)+fuck2(a%100,y%100),fuck2(a/10,y/10)+fuck1(a%10,y%10));
if (tmp+i<ret) ret=tmp+i;
}
for (int i=4; i>=1; i--)
{
b=0;
for (int k=1; k<=100; k*=10) if (a/k%10<9) b+=((a/k%10)+1)*k;
a=b;
tmp=min(fuck1(a/100,y/100)+fuck2(a%100,y%100),fuck2(a/10,y/10)+fuck1(a%10,y%10));
if (tmp+i<ret) ret=tmp+i;
}
return r3[x][y]=r3[y][x]=ret;
}

int n,s1[NN],s2[NN],s3[NN],t1[NN],t2[NN],t3[NN],dp[NN][NN];
char s[NN],t[NN];

int main()
{
memset(r1,-1,sizeof(r1));
memset(r2,-1,sizeof(r2));
memset(r3,-1,sizeof(r3));
for (int i=0; i<=9;   i++) for (int j=i; j<=9;   j++)  r1[i][j]=r1[j][i]=fuck1(i,j);
for (int i=0; i<=99;  i++) for (int j=i; j<=99;  j++)  r2[i][j]=r2[j][i]=fuck2(i,j);
for (int i=0; i<=999; i++) for (int j=i; j<=999; j++)  r3[i][j]=r3[j][i]=fuck3(i,j);
while (scanf("%s%s",s,t)!=EOF)
{
n=strlen(s);
s1[0]=s2[0]=s3[0]=s[0]-'0';
s1[1]=s[1]-'0';
s2[1]=s3[1]=(s[0]-'0')*10+s[1]-'0';
for (int i=2; i<n; i++)
{
s1[i]=s[i]-'0';
s2[i]=(s[i-1]-'0')*10+s1[i];
s3[i]=(s[i-2]-'0')*100+s2[i];
}
t1[0]=t2[0]=t3[0]=t[0]-'0';
t1[1]=t[1]-'0';
t2[1]=t3[1]=(t[0]-'0')*10+t[1]-'0';
for (int i=2; i<n; i++)
{
t1[i]=t[i]-'0';
t2[i]=(t[i-1]-'0')*10+t1[i];
t3[i]=(t[i-2]-'0')*100+t2[i];
}

if (n==1) { printf("%d\n",r1[s1[0]][t1[0]]); continue; }
if (n==2) { printf("%d\n",r2[s2[1]][t2[1]]); continue; }
if (n==3) { printf("%d\n",r3[s3[2]][t3[2]]); continue; }

for (int i=0; i<=9;  i++) dp[0][i]=r1[s1[0]][i];
for (int i=0; i<=99; i++) dp[1][i]=r2[s2[1]][i];
for (int i=0; i<=99; i++) dp[2][i]=r3[s3[2]][t1[0]*100+i];

for (int i=3; i<n; i++)
for (int j=0; j<=99; j++)
{
dp[i][j]=min3(dp[i-1][t1[i-2]*10+j/10]+r1[s1[i]][j%10],
dp[i-2][t2[i-2]]        +r2[s2[i]][j],
dp[i-3][t2[i-3]]        +r3[s3[i]][t1[i-2]*100+j]);
for (int k=0; k<=9; k++)
{
dp[i][j]=min(dp[i][j],dp[i-1][t1[i-2]*10+k]+r2[k*10+s1[i]][j]);
dp[i][j]=min(dp[i][j],dp[i-2][t1[i-3]*10+k]+r3[k*100+s2[i]][t1[i-2]*100+j]);
}
for (int k=0; k<=99; k++)
{
dp[i][j]=min(dp[i][j],dp[i-1][k]+r3[k*10+s1[i]][t1[i-2]*100+j]);
}
}
printf("%d\n",dp[n-1][t2[n-1]]);
}
return 0;
}