3049 舞蹈家怀特先生

Posted 神犇(shenben)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3049 舞蹈家怀特先生相关的知识,希望对你有一定的参考价值。

3049 舞蹈家怀特先生

 

 时间限制: 1 s
 空间限制: 64000 KB
 题目等级 : 黄金 Gold
 
 
题目描述 Description

怀特先生是一个大胖子。他很喜欢玩跳舞机(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单位。

输入描述 Input Description

第一行N,表示有N个时刻 1<=N<=10000
第二到n+1行,每行一个数,表示需要踩得版

输出描述 Output Description

一个数,最小消耗体力

样例输入 Sample Input

2

1

1

样例输出 Sample Output

3

数据范围及提示 Data Size & Hint

n<=10000

分类标签 Tags 点此展开 

 
题解:

根据题目描述,只有一开始会站在0这个格子上,以后不会向这个格子移动

假设f[i][j][k] 为 当前时间i,两只脚分别在j,k两个格子上的最小体力花费

第i个时间的状态为f[i][a[i]][k]或者f[i][j][a[i]],即有一只脚在指定格子上,所以分两种情况枚举

转移方程

f[i][j][a[i]] = min(f[i][j][a[i]],f[i-1][j][k]+move(a[i],k));
f[i][a[i]][k] = min(f[i][a[i]][k],f[i-1][j][k]+move(a[i],j));(j,k∈(0,4))

AC代码:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define N 10010
int n,m,t,a[N],f[N][5][5]; 
inline int odd(int x){
    return x&1;
}
inline int move(int x,int y){
    if(x==y) return 1;
    if(!x||!y) return 2;
    if(odd(x)==odd(y)) return 4;
    return 3;
}
int main(){
    memset(f,63,sizeof f);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",a+i);
    f[0][0][0]=0;//注意从0开始枚举,因为一开始在0格子上 
    for(int i=1;i<=n;i++){
        for(int j=0;j<=4;j++){
            for(int k=0;k<=4;k++){
                f[i][j][a[i]]=min(f[i][j][a[i]],f[i-1][j][k]+move(a[i],k));
                f[i][a[i]][k]=min(f[i][a[i]][k],f[i-1][j][k]+move(a[i],j));
            }
        }
    }
    int ans=0x3f3f3f3f;
    for(int j=0;j<=4;j++){
        for(int k=0;k<=4;k++){
            ans=min(ans,f[n][j][k]);
        }
    }
    printf("%d\n",ans);        
    return 0;
}

 

以上是关于3049 舞蹈家怀特先生的主要内容,如果未能解决你的问题,请参考以下文章

舞蹈家怀特先生

CODEVS 3049 舞蹈家怀特先生

动态规划 舞蹈家怀特

汤姆怀特第4版“Hadoop”一书中讨论过jar文件的目的?

编程思想与算法

常用编程思想与算法