hdu4433 locker


locker

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1795    Accepted Submission(s): 817


Problem Description
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
 

Source
 

Recommend
zhoujiaqi2010   |   We have carefully selected several similar problems for you:   5820  5819  5818  5817  5816 
题意:给你两个字符串,要求从第一个字符串变成第二个字符串所需的最少步骤是多少,每次可以把连续1~3个字符增加或者减少。

思路:老实说刚看这题的时候我只能猜到这道题是用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);
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值