题目大意:独木桥长度L,桥上有M个石头,要过桥,起点0,只要跳到或者跳过L都算过了,每次跳跃距离是S~T之间的整数值,问跳过桥最少需要踩到的石子数
dp[i]表示跳跃了距离i,最少需要踩到的石子数。
stone[i]表示在距离i有无石头。
状态转移方程:dp[i] = min(dp[i], dp[i-j]+stone[i]);
可是L <= 1e9, 太大了。。。爆数组的节奏,所以将距离压缩处理
!!!压缩处理:因为跳跃的距离是S~T之间的整数值,即最多条T那么两个石块之间的距离有若干个T就没意义了。则两块石头之间的距离dis就可以压缩为dis = dis % T + T;
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 20010;//(2 * t)* m
const int INF = 2147483640;
int dp[maxn], stone[maxn];//压缩处理并记录该处有无石头bool值
int a[110];//记录第i块石头的位置
int main()
{
int l, s, t, m, i, j;
memset(dp, 0x3f, sizeof(dp));
scanf("%d", &l);
scanf("%d %d %d", &s, &t, &m);
a[0] = 0;
for(i = 1; i <= m; ++i) scanf("%d", &a[i]);
a[m+1] = l;
sort(a, a + m + 2);
int dis = 0;
stone[0] = 0;
for(i = 1; i <= m+1; ++i)
{
if(a[i] - a[i-1] >= t)
dis += (a[i] - a[i-1]) % t + t;//压缩
else dis += a[i] - a[i-1];
stone[dis] = 1;
}
stone[dis] = 0;//dis最后是压缩后l的映射值
dp[0] = 0;
for(i = 1; i <= dis + t - 1; ++i)
for(j = s; j <= t; ++j)
if(i - j >= 0)
dp[i] = min(dp[i], dp[i-j]+stone[i]);
int ans = INF;
for(i = dis; i <= dis + t - 1; ++i)
ans = min(ans, dp[i]);
printf("%d\n", ans);
return 0;
}