动态规划 舞蹈家怀特

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\n", ans);
}
时间: 2024-09-30 15:08:34

动态规划 舞蹈家怀特的相关文章

3049 舞蹈家怀特先生

3049 舞蹈家怀特先生 时间限制: 1 s 空间限制: 64000 KB 题目等级 : 黄金 Gold 题目描述 Description 怀特先生是一个大胖子.他很喜欢玩跳舞机(Dance Dance Revolution, DDR),甚至希望有一天人家会脚踏“舞蹈家怀特先生”.可惜现在他的动作根本不能称作是在跳舞,尽管每次他都十分投入的表演.这也难怪,有他这样的体型,玩跳舞机是相当费劲的.因此,他希望写一个程序来安排舞步,让他跳起来轻松一些,至少不要每次都汗流浃背. DDR的主要内容是用脚来

舞蹈家怀特先生

codevs 3049 舞蹈家怀特先生 http://codevs.cn/problem/3049/ 难度等级:黄金 题目描述 Description 怀特先生是一个大胖子.他很喜欢玩跳舞机(Dance Dance Revolution, DDR),甚至希望有一天人家会脚踏"舞蹈家怀特先生".可惜现在他的动作根本不能称作是在跳舞,尽管每次他都十分投入的表演.这也难怪,有他这样的体型,玩跳舞机是相当费劲的.因此,他希望写一个程序来安排舞步,让他跳起来轻松一些,至少不要每次都汗流浃背. D

CODEVS 3049 舞蹈家怀特先生

根据题目描述,只有一开始会站在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]

经典的动态规划

有一个动态规划100例...看到机房里shenben的复习资料...加上垃圾的dp....整理一下. 一.资源分配问题 tyvj 1203 机器分配 题目大意:有m个设备,n个公司,v[i][j]表示第i个公司分j个设备的贡献值.怎样分配使贡献值的和最大? 状态:前i个公司分j个设备. f[i][j]表示前i个公司分j个设备,枚举第i个公司分k个设备. 状态转移方程:f[i][j]=max{f[i-1][j-k]+v[i][k]} 这个还挺简单的. 洛谷P2736 "破锣摇滚"乐队 R

Leetcode 494 Target Sum 动态规划 背包+滚动数据

这是一道水题,作为没有货的水货楼主如是说. 题意:已知一个数组nums {a1,a2,a3,.....,an}(其中0<ai <=1000(1<=k<=n, n<=20))和一个数S c1a1c2a2c3a3......cnan = S, 其中ci(1<=i<=n)可以在加号和减号之中任选. 求有多少种{c1,c2,c3,...,cn}的排列能使上述等式成立. 例如: 输入:nums is [1, 1, 1, 1, 1], S is 3. 输出 : 5符合要求5种

活动选择的贪心算法与动态规划(未完成)

// greedy_algorithm.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include<queue> using namespace std; #define NofActivity 11 int c[NofActivity + 1][NofActivity + 1]; int reme[NofActivity + 1][NofActivity + 1]; //活动的

求不相邻金币相加和的最大值--动态规划1

求不相邻金币相加和的最大值. 输入n个金币的金币面值(正数自定义),求这些金币不相邻和的最大值. 动态规划问题1 设f(n)为第n个金币数的最大值,f(0)=0,f(1)=a[1],输入的数组从下标为1开始. f(n)=max{a[n]+f(n-2),f(n-1)}. 代码如下: import java.util.Scanner; public class Jin_bi_zui_da_zhi { public static void main(String[] args) { Scanner s

[动态规划] 黑客的攻击 Hacker&#39;s CrackDown Uva 11825

抽象为数学模型就是,  取尽可能多的互不相交的子集 ,  使得每一个子集都能覆盖全集 #include <algorithm> #include <cstring> #include <cstdio> using namespace std; int n; int P[1000],cover[1000],f[1000]; int main(){ scanf("%d", &n); for (int i = 0; i < n;i++) {

Beauty Of algorithms(七)动态规划 钢条分割 矩阵链乘 最长公共子序列 最优二叉树

1.动态规划                动态规划的方法与方法类似,英文"dynamic programming",这里的programming不是程序的意思,而是一种表格法.都是通过组合子问题的解来解决原问题,分治方法将划分为互不相交的子问题,递归的求解子问题,再将它们的解组合起来求出原问题的解.与之相反动态规划应用于子问题的重叠情况,即不同的子问题具有公共的子问题,子问题的求解是递归进行 的,将其划分为更小的子问题,动态规划,每个子问题只求解一次,将其保存在表格中,从而无需每次求