• 动态规划 舞蹈家怀特


    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

     
    动态规划! 
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<sstream>
    #include<algorithm>
    #include<queue>
    #include<deque>
    #include<iomanip>
    #include<vector>
    #include<cmath>
    #include<map>
    #include<stack>
    #include<set>
    #include<memory>
    #include<list>
    #include<string>
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    #define MAXN 10005
    #define L 31
    #define INF 1000000009
    #define eps 0.00000001
    /*
    dp[k][x][y] 表示第k步,左脚在x 状态 右脚在y 状态
    */
    //状态 0,1,2,3 上下左右  4表示在中间
    int dp[MAXN][5][5], n;
    int a[MAXN];
    int dist(int f, int t)//计算状态之间的权值
    {
        if (f == 4) return 2;
        if (t == (f + 1) % 4 || t == (f - 1 + 4) % 4) return 3;
        if (f == t) return 1;
        if (t == (f + 2) % 4 || t == (f - 2 + 4) % 4) return 4;
    }
    int main()
    {
        scanf("%d", &n);
        for (int i = 0; i < n; i++)
            scanf("%d", &a[i]), a[i]--;
        memset(dp, INF, sizeof(dp));
        dp[0][4][4] = 0;
        for (int i = 0; i < n; i++)
        {
            for (int x = 0; x < 5; x++)
            {
                for (int y = 0; y < 5; y++)
                {
                    dp[i + 1][a[i]][y] = min(dp[i + 1][a[i]][y], dp[i][x][y] + dist(x, a[i]));
                    dp[i + 1][x][a[i]] = min(dp[i + 1][x][a[i]], dp[i][x][y] + dist(y, a[i]));
                }
            }
        }
        int ans = INF;
        for (int x = 0; x < 5; x++)
            for (int y = 0; y < 5; y++)
                ans = min(dp[n][x][y], ans);
        printf("%d
    ", ans);
    }
  • 相关阅读:
    最大正数pascal程序
    部落卫队pascal解题程序
    使用递归和非递归遍历二叉树
    机器学习 Numpy库入门
    C++ 多态性和虚函数
    C++ 利用栈解决运算问题
    C++ 字符串分割
    C++继承与派生
    机器学习基础
    C++ 输出文件编码控制
  • 原文地址:https://www.cnblogs.com/joeylee97/p/7350645.html
Copyright © 2020-2023  润新知