locker
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1795 Accepted Submission(s): 817
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?
For each case, two strings with equal length (≤ 1000) consists of only digits are given, representing the current state and the secret password, respectively.
111111 222222 896521 183995
2 12
思路:老实说刚看这题的时候我只能猜到这道题是用dp,至于怎么dp完全没有思路,然后上网搜了一大堆的题解,说得都不太清楚,不过结合多个人的思维总算得出了我自己的答案。说一下思路吧。基本上第一步的思路我看过很多篇文章都是一样的,dp[i][j][k]表示前i位匹配好了,第i+1位是j,第i+2位是k的最小步骤数。后面的思路就各有千秋了,老实说基本上我都没看懂他们写什么,这里我讲一下我的具体思路。我们从第i位递推到第i+1位,前i位匹配好了,那么如果要匹配第i+1位所需的步骤就和j有关,计算出j必须增加多少和必须减少多少才是所需要的数(计算结果我们先用xx表示吧),然后我们可以每次增加或减少1~3位数,因为是连续,所以第i+2位增加或减少的步数肯定比第i+1位少(也就是比xx少,这里用l表示),同理第i+3位的步数也肯定比第i+2位少(用m表示)。那么动态转移方程就出来了。
选择增加的情况:
dp[i + 1][(k + l) % 10][第一个字符串上第i+3位的数+ m) % 10] = min(dp[i + 1][(k + l) % 10][(第一个字符串上第i+3位的数 + m) % 10], dp[i][j][k] + xx);
选择减少的情况:
dp[i + 1][(k - l + 10) % 10][(第一个字符串上第i+3位的数 - m + 10) % 10] = min(dp[i + 1][(k - l + 10) % 10][(第一个字符串上第i+3位的数- m + 10) % 10], dp[i][j][k] + xx);
最后只要找出最小值就好了,下面给代码。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<string>
#include<queue>
#include<cmath>
#include<set>
using namespace std;
#define maxn 2000000
#define MOD 110119
typedef long long LL;
int main(){
char s1[1005], s2[1005];
int ori[1005], tg[1005];
while (scanf("%s%s", s1, s2) != EOF){
int slen = strlen(s1);
for (int i = 0; i < slen; i++){
ori[i + 1] = s1[i] - '0';
tg[i + 1] = s2[i] - '0';
}
int dp[1005][10][10];
for (int i = 0; i <= slen; i++){
for (int j = 0; j < 10; j++){
for (int k = 0; k < 10; k++){
dp[i][j][k] = maxn;
}
}
}
ori[slen + 1] = 0;
ori[slen + 2] = 0;
ori[slen + 3] = 0;
dp[0][ori[1]][ori[2]] = 0;
for (int i = 0; i < slen; i++){
for (int j = 0; j < 10; j++){
for (int k = 0; k < 10; k++){
if (dp[i][j][k] < maxn){
int xx = (tg[i + 1] - j + 10) % 10; //+
int yy = (j - tg[i + 1] + 10) % 10;//-
for (int l = 0; l <= xx; l++){
for (int m = 0; m <= l; m++){
dp[i + 1][(k + l) % 10][(ori[i + 3] + m) % 10] = min(dp[i + 1][(k + l) % 10][(ori[i + 3] + m) % 10], dp[i][j][k] + xx);
}
}
for (int l = 0; l <= yy; l++){
for (int m = 0; m <= l; m++){
dp[i + 1][(k - l + 10) % 10][(ori[i + 3] - m + 10) % 10] = min(dp[i + 1][(k - l + 10) % 10][(ori[i + 3] - m + 10) % 10], dp[i][j][k] + yy);
}
}
}
}
}
}
int ans = maxn;
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
ans = min(ans, dp[slen][i][j]);
printf("%d\n", ans);
}
}