洛谷P1052 过河(NOIp2005)

DP

题目传送门

DP应该比较好想,主要是怎么压缩距离。

因为L有1e9,而s和t只有10,因此我们可以考虑在s和t上做文章。压缩距离需要保证不管怎么跳,最终状态都是等价的。

lcm=LCM(s,s+1,,t) ,则对于所有间隔>lcm的石子,把距离%lcm+lcm。因为不论怎么跳,总会跳到lcm这个点。而两个石子之间不会有石子,因此可以把lcm这块给省掉去。然后直接做DP就可以啦!

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 1000000
using namespace std;
int s,t,l,n,lcm;
int f[MAXN+5],a[MAXN+5],st[MAXN+5];
int gcd(int a,int b){
    if (!b) return a;
    return gcd(b,a%b);
}
int main(){
    scanf("%d%d%d%d",&l,&s,&t,&n);
    lcm=1;
    for (int i=s;i<=t;i++) lcm=lcm*i/gcd(lcm,i);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    sort(a+1,a+n+1);
    int k=0;
    for (int i=1;i<=n;i++){
        int m=a[i]-a[i-1];//压缩距离
        if (m>lcm) m=m%lcm+lcm;
        st[k+m]=1; k+=m;
    }
    memset(f,0x3f,sizeof(f)); f[0]=0;
    for(int i=s;i<=k+t;i++){//DP
        for (int j=s;j<=t;j++)
            f[i]=min(f[i-j],f[i]);
        f[i]+=st[i];//st[i]表示这里是否有石头
    }
    int ans=1e8;
    for (int i=k;i<=k+t;i++)//因为有可能跳出,因此最后需要统计到k+t
        ans=min(ans,f[i]);
    printf("%d\n",ans);
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值