uva 1291 dp

来源:互联网 发布:淘宝美工每天工作任务 编辑:程序博客网 时间:2024/03/29 18:51
UVA 1291 - Dance Dance Revolution

有一个跳舞机。原点为0,有四个方向,上左下右,分别标成(1234),初始玩家两只脚站在 0 位置,跳舞机会给出一串数字,玩家要按照顺序踩下四个方向的数字。移动脚会消耗玩家的能量,从0位置移动到四个方向消耗2点能量,从一个方向移动到另一个相邻的方向消耗3点能量,从一个方向移动到相反方向消耗4点能量,原点踩一下消耗1点能量。问你踩出这串数子最少要花多少能量。


根据能量消耗关系,我们可以发现当前两只脚踩的方向才是重点。然而要记录两只脚的方向么?其实不用,因为我们可以发现两只脚的状态是互不影响的,而且单跳到第i个数字的时候,有一只脚的位置是确定的。


dp[i][j]表示跳到第i个数字的时候那只不确定的脚的位置是j的时候所消耗能量的最小值。那么跳第i+1个数字的时候可以由两只脚(a[i], j)跳过去,将会有两种结果(a[i+1], j) 和(a[i+1], a[i])。得到两个状态dp[i+1][j], dp[i+1][a[i]]。

dp[i+1][j] = dp[i+1][j] + _get(a[i], a[i+1]);
dp[i+1][a[i]] = dp[i+1][j] + _get(j, a[i+1]);

_get(a, b) 求出a跳到b所消耗的能量。其实就是几个特判。

然后在dp[n][*]里面找个最小值。


#include <bits/stdc++.h>using namespace std;const int INF = 999999999;int k;int a[100010];int _read() {int tmp;for ( k=1; scanf("%d", &tmp) && tmp; ) {// cout << tmp << endl;a[k++] = tmp;}// a[k++] = tmp;return k;}int dp[100010][5];int _get(int a, int b) {if (a == 0) return 2;if (a == b) return 1;if (abs(a-b) == 1 || abs(a-b) == 3) return 3;if (abs(a-b) == 2) return 4;}int main () {// cout << "*" << endl;for (; _read() != 1; ) {// cout << k << endl;for (int i=0; i<=k; i++) {fill(dp[i], dp[i]+5, INF);}dp[1][0] = _get(0, a[1]);for (int i=2; i<k; i++) {for (int j=0; j<=4; j++) {dp[i][j] = min(dp[i][j], dp[i-1][j] + _get(a[i-1], a[i]));dp[i][a[i-1]] = min(dp[i][a[i-1]], dp[i-1][j] + _get(j, a[i]));}}int ans = INF;for (int i=0; i<=4; i++) {ans = min(ans, dp[k-1][i]);}printf("%d\n", ans);}return 0;}


0 0
原创粉丝点击