本题的入手点在于分别考虑解决问题的难点,以及巧妙地暴力。
- 在不考虑 n 的数据规模的情况下,可以根据每个查询暴力解出答案(用变量的变化模拟 p 的移动)。
- 在不考虑 k 的数据规模的情况下,可以进行动态规划。令 d[i][j] 表示当前起始位置为 i , k 为 j 的情况下需要多少步能够走出数组,那么按照 i 从大到小的顺序 DP 就能得到答案 d[p][k] 。
但是本题的问题在于 n 和 k 的数据规模必须同时被考虑。在这种情况下,当 k 比较小的时候(比如小于 100 的时候)我们可以动态规划,当 k 比较大的时候,我们可以暴力。
毕格斯茅问题
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 5;
int dp[maxn][505], a[maxn], n, p, q, k;
int calc(int p, int k)
{
int cnt = 0;
while(p <= n)
{
cnt++;
p = p + a[p] + k;
}
return cnt;
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for(int i = n; i >= 1; i--)
for(int j = 1; j <= 500; j++)
{
if(i+a[i]+j > n) dp[i][j] = 1;
else dp[i][j] = dp[i+a[i]+j][j]+1;
}
scanf("%d", &q);
while(q--)
{
scanf("%d%d", &p, &k);
if(k <= 500)
printf("%d\n", dp[p][k]);
else
printf("%d\n", calc(p, k));
}
return 0;
}