luogu P1052 过河

本文介绍了一道动态规划难题的解决思路,通过路径压缩和步长优化将原问题规模从1e9降低,确保了解决方案的有效性和可行性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题解

一道难点不在于dp的dp题目。转移公式很简单

for( i = 1->n )
    for( step = s ->t )
        f[i] = min(self, f[i-step] + v[i])// v[i]:在i处有无石头

我脑子比较抽用的max()来递推的,其实也一样。
但是这条路有 1e9 长,直接下去是肯定超内存又超时的,必须要想办法把无用的路减少点。
有很多办法可以优化,不限于 路径压缩,离散化等。(我都不懂)
看到个比较易懂的,因为步长只在1-10内,其最小公倍数为2520,意思是对2520外的那个点
在此处总是有办法到的。那么就可以把相隔超过2520的石头点间距减少,这样就可以把路长缩短了。


Code

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int  N = 800000; 
const int INF = -9999999;
int n,m;

int f[N];
int cot[102];

int main(){

    int s,t;
    cin>>n>>s>>t>>m;

    int tot=1;
    for(int i=0;i<m;i++){
        cin>>cot[tot++];
    }
    sort(cot+1,cot+1+m);

    if(s==t){ // 特例判断
        tot=0;
        for(int i=1;i<=m;i++)
            if(cot[i]%s==0) tot++;
        cout<<tot<<endl;
        return 0;
    }

    int dis;
    cot[m] = n;
    for(int i=1;i<=m+1;i++){ // 压缩距离
        dis=cot[i]-cot[i-1];
        if(dis>2520){
            dis/=2520;
            cot[i]-= dis*2520;
        }
    }
    n = cot[m]; 
    cot[m]=0;   
    int v;

    tot=1;
    f[0] = 0;
    for(int pos = 1; pos<=n+10;pos++){ // dp
        if(cot[tot] == pos) { tot++;v=-1;}
        else v =0;

        f[pos] = INF;
        for(int st = s;st<=t;st++){
            if(pos-st<0 || f[pos-st]==INF)continue;
            f[pos] = max(f[pos],f[pos-st]+v);
        }
    }

    int ans = INF;
    for(int p=n;p<n+10;p++){
        if(f[p]>ans) ans = f[p];
    }
    cout<< -ans<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值