P1052 过河(离散化+dp)

P1052 过河

dp不难,重点是要想到离散化

石子个数$<=100$意味着有大量空间空置,我们可以缩掉这些空间。

实现的话自己yy下就差不多了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define re register
using namespace std;
int max(int &a,int &b){return a>b?a:b;}
int min(int &a,int &b){return a<b?a:b;}
int s,t,m,l,f[10000],a[102],b[10000];
int main(){
    scanf("%d%d%d%d",&l,&s,&t,&m);
    for(int i=1;i<=m;++i) scanf("%d",&a[i]);
    sort(a+1,a+m+1); int pre=0,z,d=l-a[m],tmp; //d:最后一个石子与终点的距离
    for(int i=1;i<=m;++i){
        if(a[i]-pre>=2*t){
            tmp=(a[i]-pre)%t;
            pre=a[i];
            a[i]=a[i-1]+tmp+t;
        }else z=a[i],a[i]=a[i-1]+a[i]-pre,pre=z;
    }//缩空间
    tmp=d/t-1; d-=tmp*t;
    l=a[m]+d;
    for(int i=1;i<=m;++i) b[a[i]]=1;//有石子的地方
    memset(f,127,sizeof(f)); f[0]=0;
    for(int i=1;i<=l+t;++i)
        for(int j=max(0,i-t);j<=i-s;++j)
            f[i]=min(f[i],f[j]+b[i]);
    int ans=1e9;
    for(int i=l;i<=l+t;++i) ans=min(ans,f[i]);//注意可以超出终点,这意味着答案是一个范围。
    printf("%d",ans);
    return 0;
}

 

posted @ 2018-10-17 21:04  kafuuchino  阅读(301)  评论(0编辑  收藏  举报