2012天津C题

行李箱上的密码锁大家都知道, 现在给我们长度为n(n<=1000)的两个密码串,每次可以转动连续的1->3个字符1格,问最少多少次可以使得第一个串变成第二个串

经历了搜索,贪心,的思路后,最终想到了动态规划。

因为第一个字符如果不在位,那么肯定是要处理的,否则那么相当于子问题。

所以定义dp[i][k1][k2]为第i个字符在位时,第i+1个字符向上走了k1格,第i+2个字符向上走了k2格。

当状态为dp[i][k1][k2]时,为了要使的第i+1在位,

那么可以向上走 t = (des[i] - (src[i]+10)%10 + 10)%10  步

或者向下走 t = 10 - t 步

那么第i+2个可以走0<=a<=t步

而第i+2个可以走0<=b<=a步,   这个没考虑到,wa了好久。

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <algorithm>
 5 using namespace std;
 6 const int INF = 1<<30;
 7 int dp[1000+10][11][11];
 8 char src[1000+10],des[1000+10];
 9 int main()
10 {
11     //freopen("/Users/whoami/in.txt", "r", stdin);
12     while(scanf("%s%s",src,des)!=EOF)
13     {
14         int n = strlen(src);
15         for(int i=0;i<=n;++i)
16             for(int k1=0;k1<10;++k1)
17                 for(int k2=0;k2<10;++k2)
18                     dp[i][k1][k2] = INF;
19         dp[0][0][0] = 0;
20         for(int i=0;i<n;++i)
21         {
22             for(int k1=0;k1<10;++k1)
23                 for(int k2=0;k2<10;++k2)
24                 {
25                     if(dp[i][k1][k2]==INF)continue;
26                     int t = (des[i] - src[i] - k1+20)%10;
27                     for(int a=0;a<=t;++a)
28                     {
29                         for(int b=0;b<=a;++b)
30                             dp[i+1][(k2+a)%10][b] = min(dp[i+1][(k2+a)%10][b],dp[i][k1][k2]+t);
31                     }
32                    
33                     t = 10 - t;
34                     for(int a=0;a<=t;++a)
35                     {
36                         for(int b=0;b<=a;++b)
37                             dp[i+1][(k2-a+10)%10][(10-b)%10] = min(dp[i+1][(k2-a+10)%10][(10-b)%10],dp[i][k1][k2]+t);
38                     }
39                     
40                 }
41             
42         }
43         printf("%d
",dp[n][0][0]);
44         }
45     return 0;
46 }
原文地址:https://www.cnblogs.com/justPassBy/p/4915703.html