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 }
时间: 2024-11-07 22:26:28