一道dp题,虽然知道是dp,但是不会做;
学习了ACM_cxlove大神的代码,终于明白了;
搬运工:
dp[i][j][k]表示 前i个已经完全匹配,而这时候,第i+1个已经加了j位,第i+2位已经加了k
转移分为两步,枚举加,枚举减;
上面是大神的原话,不过看了好久的代码才明白;
下面是我的一点领悟:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define inf 1<<20 5 #define N 1005 6 using namespace std; 7 char s1[N],s2[N]; 8 int dp[N][10][10]; 9 int main() 10 { 11 while(scanf("%s%s",s1,s2)!=EOF) 12 { 13 int l=strlen(s1); 14 for(int i=0; i<=l; i++) for(int j=0; j<10; j++) for(int k=0; k<10; k++) dp[i][j][k]=inf; 15 dp[0][0][0]=0; 16 for(int i=0; i<l; i++)//表示要排到了第i位; 17 for(int j=0; j<10; j++)//第i位移动的数量; 18 for(int k=0; k<10; k++)//第i+1位移动的数量; 19 { 20 int t=(s2[i]-s1[i]-j+20)%10;//枚举向上移动的数目; 21 for(int a=0; a<=t; a++)//第i+1移动的数目; 22 for(int b=0; b<=a; b++)//第i+2位移动的数目; 23 dp[i+1][(k+a)%10][b]=min(dp[i+1][(k+a)%10][b],dp[i][j][k]+t);//排好第i位的状态转移到i+1位; 24 t=10-t;//枚举向下移动的数目; 25 for(int a=0; a<=t; a++) 26 for(int b=0; b<=a; b++) 27 dp[i+1][(k-a+10)%10][(10-b)%10]=min(dp[i+1][(k-a+10)%10][(10-b)%10],dp[i][j][k]+t); 28 } 29 printf("%d ",dp[l][0][0]); 30 } 31 return 0; 32 }