密码锁 Locker

密码锁 Locker_第1张图片
UVA1631
定义 d p [ i ] [ x ] [ y ] [ z ] dp[i][x][y][z] dp[i][x][y][z]为达到第 i i i个数字之前已经解锁,第 i i i个数为 x x x,第 i + 1 i+1 i+1个数为 y y y,第 i + 2 i+2 i+2个数为 z z z的状态最少需要转动几下。
详见注释
AC代码

#include
#include
#include
#include
#include
#include
#include
using namespace std;
constexpr static int inf = 0x3f3f3f3f;
char Start[1002], End[1002];
int dp[1001][10][10][10];
int Len;
int DP(int Cur,int x,int y,int z) {
     
	if (Cur >= Len) {
     
		return 0;
	}
	int& Ans = dp[Cur][x][y][z];
	if (Ans != inf) {
     
		return Ans;
	}
	//还需向上转动几次才能使第Cur位解锁
	int&& Upper = (End[Cur] - x + 10) % 10;
	//在向上转Upper次第Cur位时,枚举所有的Cur+1,Cur+2位的可能
	for (int i = 0; i <= Upper; ++i) {
     
		for (int j = 0; j <= i; ++j) {
     
			Ans = min(Ans, DP(Cur + 1, (y + i) % 10, (z + j) % 10, Start[Cur + 3]) + Upper);
		}
	}
	//枚举向下转
	int&& Downer = (x - End[Cur] + 10) % 10;
	for (int i = 0; i <= Downer; ++i) {
     
		for (int j = 0; j <= i; ++j) {
     
			Ans = min(Ans, DP(Cur + 1, (y - i + 10) % 10, (z - j + 10) % 10, Start[Cur + 3]) + Downer);
		}
	}
	return Ans;
}
int main() {
     
	while (scanf("%s%s", Start, End) != EOF) {
     
		Len = strlen(Start);
		memset(dp, 0x3f, sizeof(dp));
		for (int i = 0; i < Len; ++i) {
     
			Start[i] -= '0';
			End[i] -= '0';
		}
		//令最后一位+1,最后一位+2相同,代表往后加两位已经转好的,方便枚举
		Start[Len] = Start[Len + 1] = End[Len] = End[Len + 1] = 0;
		cout << DP(0, Start[0], Start[1], Start[2]) << endl;
	}
	return 0;
}

你可能感兴趣的:(#,动态规划,动态规划,算法,动态规划求解,递归法,c++)