悦动达人

Description

一个游戏,在屏幕上有5个格子形成一行,每一秒都会有一个格子闪烁,格子闪烁时你需要保证至少有一只手指在格子上面, 现在我们已经知道第i秒时,第xi个格子会闪烁,我们假设手指的移动不花费时间,你现在用两根手指玩这个游戏, 设初始两根手指都在0处位置,算出n秒过后手指需要移动的最小距离。(允许手指交叉)

注:手指移动的距离的计算是,假设你的一根从x,移动到y格,那么移动的距离是|x-y|

Input

第一行一个数T,表示有T组测试数据(T<=50) 第二行,n,表示进行n秒(1<=n<=10^4) 下一行 n个数,xi(0<=xi<=4)

Output

输出n秒过后手指需要移动的最小距离.

Sample Input

1 2 0 2

Sample Output

2

HINT

DP题

dp[i][j][k]表示两个手指在i位置和j位置的时候走到第k步所最少需要的移动距离。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <string>
 5 #include <cmath>
 6 #include <algorithm>
 7 using namespace std;
 8 int T, n;
 9 int dp[5][5][10010];
10 int mark[10010];
11 int main(){
12     scanf("%d", &T);
13     while(T--){
14         scanf("%d", &n);
15         for(int i = 1; i <= n; i++){
16             scanf("%d", &mark[i]);
17         }
18         memset(dp, -1, sizeof(dp));
19         dp[0][0][0] = 0;
20         for(int k = 1; k <= n; k++){
21             for(int i = 0; i < 5; i++){
22                 for(int j = 0; j < 5; j++){
23                     if(dp[i][j][k-1] == -1) continue; //这种状态不存在。
24                     int d = abs(i-mark[k]);
25                     if(dp[mark[k]][j][k] == -1) dp[mark[k]][j][k] = dp[i][j][k-1]+d;
26                     else  dp[mark[k]][j][k] = min( dp[mark[k]][j][k],dp[i][j][k-1]+d);
27                     d = abs(j-mark[k]);
28                     if(dp[i][mark[k]][k] == -1) dp[i][mark[k]][k] = dp[i][j][k-1]+d;
29                     else  dp[i][mark[k]][k] = min( dp[i][mark[k]][k],dp[i][j][k-1]+d);
30                 }
31             }
32         }
33         int min = 99999999;
34         for(int i = 0; i < 5; i++){
35             for(int j = 0; j < 5; j++){
36                 if(dp[i][j][n] != -1 && dp[i][j][n] <= min) min = dp[i][j][n];
37             }
38         }
39         printf("%d\n", min);
40     }
41     return 0;
42 }

 

posted @ 2015-03-16 18:20  下周LGD该赢了吧  阅读(142)  评论(0编辑  收藏  举报