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\n",dp[n][0][0]); 44 } 45 return 0; 46 }