描述
怀特先生是一个大胖子。他很喜欢玩跳舞机(Dance Dance Revolution, DDR),甚至希望有一天人家会脚踏“舞蹈家怀特先生”。可惜现在他的动作根本不能称作是在跳舞,尽管每次他都十分投入的表演。这也难怪,有他这样的体型,玩跳舞机是相当费劲的。因此,他希望写一个程序来安排舞步,让他跳起来轻松一些,至少不要每次都汗流浃背。
DDR的主要内容是用脚来踩踏板。踏板有四个方向的箭头,用1 (Up)、2 (Left)、3 (Down)、4 (Right)来代表,中间位置由0来代表。每首歌曲有一个箭头序列,游戏者必须按照或这个序列一次用某一只脚踩相应的踏板。在任何时候,两只脚都不能在同一踏板上,但可以同时待在中心位置0。
每一个时刻,它必须移动而且只能移动他的一只脚去踩相应的箭头,而另一只脚不许移动。跳完一首曲子之后,怀特先生会计算他所消耗的体力。从中心移动到任何一个箭头耗费2单位体力,从任何一个箭头移动到相邻箭头耗费3单位体力,移动到相对的箭头(1和3相对,2和4相对)耗费4单位体力,而留在原地再踩一下只需要1单位。怀特先生应该怎样移动他的双脚(即,对于每个箭头,选一只脚去踩它),才能用最少的体力完成一首给定的舞曲呢?
例如,对于箭头序列Left (2), Left (2), Up (1), Right (4),他应该分别用左、左、右、右脚去踩,总的体力耗费为2+1+2+3=8单位。
DDR的主要内容是用脚来踩踏板。踏板有四个方向的箭头,用1 (Up)、2 (Left)、3 (Down)、4 (Right)来代表,中间位置由0来代表。每首歌曲有一个箭头序列,游戏者必须按照或这个序列一次用某一只脚踩相应的踏板。在任何时候,两只脚都不能在同一踏板上,但可以同时待在中心位置0。
每一个时刻,它必须移动而且只能移动他的一只脚去踩相应的箭头,而另一只脚不许移动。跳完一首曲子之后,怀特先生会计算他所消耗的体力。从中心移动到任何一个箭头耗费2单位体力,从任何一个箭头移动到相邻箭头耗费3单位体力,移动到相对的箭头(1和3相对,2和4相对)耗费4单位体力,而留在原地再踩一下只需要1单位。怀特先生应该怎样移动他的双脚(即,对于每个箭头,选一只脚去踩它),才能用最少的体力完成一首给定的舞曲呢?
例如,对于箭头序列Left (2), Left (2), Up (1), Right (4),他应该分别用左、左、右、右脚去踩,总的体力耗费为2+1+2+3=8单位。
输入格式
第一行N,表示有N个时刻
第二到n+1行,每行一个数,表示需要踩得版
第二到n+1行,每行一个数,表示需要踩得版
输出格式
一个数,最小消耗体力
测试样例1
输入
2
1
1
输出
3
备注
n<=10000
分析
多阶段决策DP。A[i]表示第i个舞步的位置,F(l, r, k)表示左脚踩l,右脚踩r,完成k步所花的体力值,C(a, b)表示脚从a挪到b所花费的体力。方程:
F(0, 0, 0) = 0;
F(A[i], r, i) = min{F(l, r, i-1) + C(l, A[i])};
F(l, A[i], i) = min{F(l, r, i-1) + C(r, A[i])}
用滚动数组其实可以节省不少空间,但这题数据量不大没有必要。
代码
1 #include <iostream> 2 using namespace std; 3 const int C[5][5] = {{1, 2, 2, 2, 2}, {0, 1, 3, 4, 3}, {0, 3, 1, 3, 4}, {0, 4, 3, 1, 3}, {0, 3, 4, 3, 1}}; 4 int F[5][5][10001]; 5 int A[10001]; 6 int n, ans; 7 int main() 8 { 9 cin >> n; 10 for (int i = 1; i <= n; ++i) 11 cin >> A[i]; 12 for (int i = 0; i <= n; ++i) 13 for (int l = 0; l != 5; ++l) 14 for (int r = 0; r != 5; ++r) 15 F[l][r][i] = 200000000; 16 F[0][0][0] = 0; 17 ans = 200000000; 18 for (int i = 1; i <= n; ++i) { 19 for (int l = 0; l != 5; ++l) { 20 for (int r = 0; r != 5; ++r) { 21 if ((l != r) || (l == r && l == 0)) { 22 if (F[l][r][i - 1] + C[l][A[i]] < F[A[i]][r][i]) 23 F[A[i]][r][i] = F[l][r][i - 1] + C[l][A[i]]; 24 if (F[l][r][i - 1] + C[r][A[i]] < F[l][A[i]][i]) 25 F[l][A[i]][i] = F[l][r][i - 1] + C[r][A[i]]; 26 } 27 } 28 } 29 } 30 for (int l = 0; l != 5; ++l) 31 for (int r = 0; r != 5; ++r) 32 if (F[l][r][n] < ans) 33 ans = F[l][r][n]; 34 cout << ans; 35 return 0; 36 }