[多维DP] UVa10618 跳舞机(复杂DP的最优解输出问题)

题目

这里写图片描述
这里写图片描述

思路

本题的题目可以说是很长了,描述的内容也很多,这还是LRJ精简后的结果。对于此类题,一方面要抓住各个题目规定不能出现的特殊情况,另一方面也要注意在信息量庞大的情况下对题目主干准确头脑清醒的把握。
啥意思呢,第一次我做的时候,根据LRJ的提醒,犄角旮旯的每一个特判都找到地清清楚楚,却没看到最重要的。一直以为消耗能量是“上一只脚……”,而描述的是“这只脚上一次”,就因为这个,卡了一上午。。


本题属于那种大体思路好掌握,但细节很多的题。
大体思路是这样的,本题总体是属于多阶段决策问题,由需要按的箭头划分阶段,而区分每个阶段的属性有左右脚的位置和上一次的移动(记录上一次移动的原因是判断本次移动的能量消耗会用到),所以用d(i, a, b, s)来表示遍历到第i个箭头,左右脚分别在a和b上(0,1,2,3分别表示上左右下),上一次移动的是脚s(s=0表示没有脚动,s=1表示左脚动,s=2表示右脚动)的情况下最少能量消耗。
状态的转移也是明显的,如果这步是4个箭头之一,有两种决策:左脚移动到该箭头,右脚移动到该箭头。如果这步是”.”,有三种决策:左脚移动到一个箭头,右脚移动到一个箭头,不动。注意不要转移题目种提到的特殊情况就行。
边界是i>n,d(i,…,…,…) = 0。答案是d(0,1,2,0)。


最优解的输出问题。
很多DP只要求输出最优解的值,但本题要求完完整整地输出最优解。最早讨论输出最优解是在硬币问题,分别讨论了分别针对记忆化搜索和递推的两种输出方式。本题输出解的方式看上去像是循环,实际也是递归输出。要注意的是,这种多维复杂DP的动作函数opt,正确的形式应该是opt[maxn][4][4][3],即对应每一个状态,而不是简单的opt[maxn]。
正常情况下还需要有一个数组p[maxn][4][4][3]来保存一个状态的父状态,但本题不需要,直接根据本状态就可以推出上一个状态,递归即可。


可以看到的是,本题的特判实在dp函数的开头处,而不是在决策转移处。我感觉是自己小聪明了一把,因为把特判写在dp函数的开头,可以避免在关键转移的时候太复杂的代码结构。但同样有一些麻烦,就是递归到这个函数的时候,上个函数的某些数据(比如oldab)已经没了,需要靠上一个函数传一下。

代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define _for(i,a,b) for(int i = (a); i<(b); i++)
#define _rep(i,a,b) for(int i = (a); i<=(b); i++)
using namespace std;

const int INF = 100000;
const int maxn = 70 + 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值