码迷,mamicode.com
首页 > 其他好文 > 详细

uva 1291 dp

时间:2015-08-25 23:42:46      阅读:191      评论:0      收藏:0      [点我收藏+]

标签:dp   uva   acm   

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;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

uva 1291 dp

标签:dp   uva   acm   

原文地址:http://blog.csdn.net/xuelanghu407/article/details/47988559

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!