1550. 最小步数(steps)

1550. 最小步数(steps)

题目描述
从起点到终点有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

方法一(记忆化搜索):

记忆化:
对于第i格,我们走了step步时所得到的最多money,用f[i,step]表示。

那么接下来用到两个剪枝:

  1. 当走到第i格的步数还>=当前走到终点的最优步数时,就剪枝。
  2. 当走到第i格使用了step步时的money还<=f[i,step],就剪枝。
#include
#include
#include
#include
#include
#include
#include
#include
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
const int MAX=2147483647;
const int N=1e6;
int n,f[200][200],a[1010],ans=MAX;
void dfs(int i,int money,int step)
{
	if(step+1>=ans||f[i][step]>=money) return;
	f[i][step]=money;
	if(i==n) 
	{
		if(f[i][step]+a[i]>=0) ans=step+1;
		return;	
	}
	if(money-100>=0)  dfs(i+1,money-100,step);
	if(a[i]+money>=0) dfs(i+1,money+a[i],step+1);	
}
int main()
{
	//fre(steps);
	memset(f,-1,sizeof(f));
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	dfs(1,0,0);
	if(ans==MAX) printf("-1");
	else printf("%d",ans);
	return 0;
}

方法二(dp):
我们设f[i][j][0]表示第i格走了j步,并且第i格用了走的策略所获得的最多money;f[i][j][1]表示第i格走了j步,并且第i格用了跳过的策略所获得的最多money。

这两个状态是由第i-1格的状态转移而来。

动态转移方程:

  1. 当选择走的策略:
    t = m a x ( f [ i − 1 ] [ j − 1 ] [ 0 ] , f [ i − 1 ] [ j − 1 ] [ 1 ] ) t=max(f[i-1][j-1][0],f[i-1][j-1][1]) t=max(f[i1][j1][0],f[i1][j1][1])

f [ i ] [ j ] [ 0 ] = t + a [ i ] ( t + a [ i ] > = 0 ) f[i][j][0]=t+a[i](t+a[i]>=0) f[i][j][0]=t+a[i](t+a[i]>=0)

2.当选择跳过的策略:
t = m a x ( f [ i − 1 ] [ j ] [ 0 ] , f [ i − 1 ] [ j ] [ 1 ] ) t=max(f[i-1][j][0],f[i-1][j][1]) t=max(f[i1][j][0],f[i1][j][1])

f [ i ] [ j ] [ 1 ] = t − 100 ( t > = 100 ) f[i][j][1]=t-100(t>=100) f[i][j][1]=t100(t>=100)

初始化,由于我们f[][][]所存的值为最大值,所以一开始要赋为(-无穷 )。
但对于第一步,就只能选走的策略,
即:f[1][1][0]=a[1];

#include
#include
#include
#include
#include
#include
#include
#include
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
const int MAX=2147483647;
const int N=1e6;
int n,t,a[110],f[200][200][2];
int main()
{
	//fre(steps);
	memset(f,-127/3,sizeof(f));
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	f[1][1][0]=a[1];
	for(int i=1;i<=n;i++)
		for(int j=1;j<=i;j++)
		{
			t=max(f[i-1][j][0],f[i-1][j][1]);
			if(t>=100&&i<n) f[i][j][1]=t-100;
			t=max(f[i-1][j-1][0],f[i-1][j-1][1]);
			if(t+a[i]>=0) f[i][j][0]=t+a[i];
		}
	for(int i=1;i<=n;i++)
		if(f[n][i][0]>=0) {printf("%d",i);return 0;}
	printf("-1");	
	return 0;
}

你可能感兴趣的:(模拟赛,动态规划,dfs)