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

被yobobobo的五十行代码给鄙视了!~写挫鸟~~

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;
}


你可能感兴趣的:(HDOJ4433-locker,2012ACM天津站C题,DP)