UVA 1631 Locker(HDU 4433)(DP)

A password locker with N digits, each digit can be rotated to 0-9 circularly.
You can rotate 1-3 consecutive digits up or down in one step.
For examples:
567890 → 567901 (by rotating the last 3 digits up)
000000 → 000900 (by rotating the 4th digit down)
Given the current state and the secret password, what is the minimum amount of steps you have
to rotate the locker in order to get from current state to the secret password?

Input
Multiple (less than 50) cases, process to EOF.
For each case, two strings with equal length (≤ 1000) consists of only digits are given, representing
the current state and the secret password, respectively.

Output
For each case, output one integer, the minimum amount of steps from the current state to the secret
password.

Sample Input
111111 222222
896521 183995

Sample Output
2
12

题意:给两个字符串A,B,每一步可以将连续的1-3个数字上调或下调一位,问将A变成B最少需要几步。


思路:调动一位只能对它的后两位有影响,从第一位开始调,第一位只能通过它自己的变化才能变成目标数字。设dp[i][j][k]表示使i位置变为目标数字,且i+1位置变为数字j,且i+2位置变为数字k,所需要的最少步数。需要注意的一个坑数据就是,000 --> 789,只需要3步,也就是说,变第i位需要固定的x步,i+1可以只变y(y<=x)步,i+2可以只变z(z<=y)步。然后变i位的时候有上调和下调两种方式。


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

char s1[1005],s2[1005];
int a[1010],b[1010];
int n;
int dp[1005][10][10];

int main()
{
    while(scanf("%s%s",s1,s2)!=EOF)
    {
        n=(int)strlen(s1);
        for(int i=1;i<=n;i++)
        {
            a[i]=s1[i-1]-'0';
            b[i]=s2[i-1]-'0';
        }
        memset(dp,0x3f3f3f3f,sizeof(dp));
        a[n+1]=b[n+1]=0;
        a[n+2]=b[n+2]=0;
        dp[0][a[1]][a[2]]=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<10;j++)
            {
                for(int k=0;k<10;k++)
                {
                    if(dp[i-1][j][k]!=0x3f3f3f3f)
                    {
                        int x;
                        if(b[i]>=j) x=b[i]-j;     //将第i位上调x步
                        else x=10+b[i]-j;
                        dp[i][k][a[i+2]]=min(dp[i][k][a[i+2]],dp[i-1][j][k]+abs(x));
                        for(int l=0;l<=x;l++)
                        {
                            int c=(k+l+20)%10;
                            dp[i][c][a[i+2]]=min(dp[i][c][a[i+2]],dp[i-1][j][k]+abs(x));
                            for(int p=0;p<=l;p++)
                            {
                                int d=(a[i+2]+p+20)%10;
                                dp[i][c][d]=min(dp[i][c][d],dp[i-1][j][k]+abs(x));
                            }
                        }
                        //或者下调x步
                        if(b[i]


你可能感兴趣的:(动态规划)