Uva1631_分阶段动态规划

动态规划训练2——Uva1631

                    Locker
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

 观察可知,假设A={a1,a2,a3…}是一最优的转动步骤,则显然更改A中序列的顺序不影响A的最优性。
 同时又有,假若x位置已经和password对应,那么此后不转动x位置对最优解的获得无影响:一次转动的位置个数与步骤数无关。
 由以上两点,可约定如下状态:
 要获取最优解A,则我们可以先进行A中处理靠前位置的转动,当靠前位置的位置处理完成后,后续转动对其无影响,因此可以不用考虑;
 令dp[i][j][k][h]表示已经处理了i个位置,j、k、h分别表示第i+1/2/3个位置上的数字。
  由状态定义中i的连续性,规定dp[i]只能转移到dp[i+1]:
  因为若直接从i转移到i+2,情况1:i+1未完成处理,不满足连续性;
  情况2:i+1完成处理,同时又有i+2完成处理,则i+2可由i+1转移得。
  综上所述,i不能转移到i+2。
因此,根据题目条件及转移规则,转移方式易得。
初始条件dp[n]=0。

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>
#include <string.h>
#include <math.h>
#include <stdlib.h>
using namespace std;
string s, en;
int dp[1005][15][15][15],length;
const int UP = 1, DOWN = 0,INFO=1<<29;
int dis(int i, int j, int op) {
	if (op == UP)
		return (j - i + 10) % 10;
	else return (i - j + 10) % 10;
}
int DP(int n, int i, int j, int k) {
	if (n == length) return 0;
	int &ans = dp[n][i][j][k], h = (n + 3 < length ? (s[n + 3] - '0') : 0);
	if (ans != -1) return ans; 
	ans = INFO;
		for (int p = 0, d = dis(i,en[n]-'0',UP), flag = 1; p < 2; ++p, d=10-d, flag *= -1) {
			for (int a = 0; a <= d; ++a)
				for (int b = 0; b <= a; ++b)
					ans = min(ans, DP(n + 1, (j + a * flag + 10) % 10, (k + b * flag + 10) % 10, h) + d);
		}
		return ans;
}
int main(void) {
	while (cin >> s >> en) {
		length = s.length();
		memset(dp, -1, sizeof(dp)); 
		int t[3];
		for (int i = 0; i < 3; ++i)
			t[i] = (i < length ? (s[i] - '0') : 0);
		printf("%d\n", DP(0, t[0], t[1], t[2]));					
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42663062/article/details/84936488