【普及模拟】最小步数(DP)
这道题目的朴素做法是一道爆搜+双剪枝,经过一番思索这道题同样符合了DP(dynamic programming)的条件。所以这里带来一种DP的方法。
题目描述
从起点到终点有N步,如果“走”第K步,将会得到A[K]元钱,A[K]可能为负数。
你也可以花100元钱“跳过”当前的这一步,即不会得到A[K]。但是任何时刻身上的钱都必须是非负的。开始时,你身上共有0元。给定数组A,求在能到达终点的情况下最小需要走过(即不是用100元钱跳过)的步数。注意:最后一步必须走,不能选择跳过。
输入
共有两行。
第一行为整数N(0<=N<=100)。
第二行有N个整数,第K个数为A[K],-10000<=A[K]<=10000,。
输出
一个整数,表示需要走的最少步数。若无法走到终点,输出-1。
样例输入
6
30 30 30 30 30 30
样例输出
5
题目解法:我们可以根据题意知道,这道题每次经过一个点就会有两种状态(一种是用100块跳过,一种是+A[i]走过去),所以我们可以开一个三维数组F。F[i][j][0]表示走了j步到当前位置i没跳过的剩余钱数,而F[i][j][1]表示走了j步到当前位置i跳过的剩余钱数。
这时我们可以得到状态转移方程了:
f[i][j][0]=max(f[i-1][j-1][0],f[i-1][j-1][1])+a[i];
f[i][j][1]=max(f[i-1][j][0],f[i-1][j][1])-100;
注:要判断才能执行以下转移方程,钱数不能<0。
由于最后一步必须要走过去,所以我们只DP到n-1次,最后一次循环加上判断这种情况是否成立即可。
代码(讲题同学的……)
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
int i,j,m,n;
int a[101],f[101][101];
int