洛谷P1052_过河_dp_将大数据压缩处理

题目大意:独木桥长度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;
}

猜你喜欢

转载自blog.csdn.net/jay__bryant/article/details/80377503