- 最小步数题目描述
小楠正在玩一个游戏,规则为:
从起点到终点有 N 步,如果走第K 步,小楠将会得到a[K]元钱,a[K]可能为负数。小楠也可以花100元钱跳过当前的这一步,即不会得到 。但是任何时刻身上的钱都必须是非负的。
开始时,小楠身上共有 0元。给定数组A,求在能到达终点的情况下最少需要走过(即不是用100元钱跳过)的步数。
输入格式
从 steps.in
中读入数据。
第一行为整数N 。
第二行有 N 个整数,第 K个数为a[K] ,每两个数之间有一个空格隔开。
输出格式
输出到文件 steps.out
中。
输出仅一行为一个整数,表示需要走的最少步数。若无法走到终点,则输出-1。
样例输入:
6
30 30 30 30 30 30
样例输出:
5
解:
用到动态规划,f[i][j]表示到第i步,之前已经走了j步身上所能剩下的最多的金额数目;
可得转移方程:
注意:"但是任何时刻身上的钱都必须是非负的";
70分dfs:
#include <bits/stdc++.h>
using namespace std;
int n;
int a[100004];
int ans = 10005959;
void search(int now, int foot, int value) {
if (foot + 1 >= ans)
return;
if (now == 1 + n) {
ans = min(ans, foot);
return;
}
if (value >= 100)
search(now + 1, foot, value - 100);
if (value + a[now] >= 0)
search(now + 1, foot + 1, value + a[now]);
return;
}
int main() {
freopen("steps.in", "r", stdin);
freopen("steps.out", "w", stdout);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
search(1, 0, 0);
if (ans == 10005959)
cout << -1;
else
cout << ans;
return 0;
}
100分dp:
#include<bits/stdc++.h>
using namespace std;
int n,a[101],f[101][101];
int main()
{
freopen("steps.in","r",stdin);
freopen("steps.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++)
for(int j=0;j<=n;j++)
f[i][j]=-9999999;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i-1;j++)
{
if(f[i-1][j-1]>=0&&f[i-1][j-1]+a[i]>=0) f[i][j]=max(f[i][j],f[i-1][j-1]+a[i]);
if(f[i-1][j]-100>=0&&f[i-1][j]>=0) f[i][j]=max(f[i][j],f[i-1][j]-100);
}
if(f[i-1][i-1]+a[i]>=0&&f[i-1][i-1]>=0) f[i][i]=f[i-1][i-1]+a[i];
}
for(int i=1;i<=n;i++)
{
if(f[n][i]>=0)
{
cout<<i;
return 0;
}
}
cout<<-1;
return 0;
}