洛谷p1052过河

来源:互联网 发布:mysql怎么快速替换东西 编辑:程序博客网 时间:2024/06/05 22:51

原题

先想一下思路,由于是区间跳跃,不能用贪心,那么f[i]表示跳到i时最少踩到的石子数,i只能由i-t~i-s转移过来,所以选择其中的最小值跳,保证f[i]最小。

但是l太大了,1e9,但是m和t很小,就是1e9中有很多没有用的空间,我们求终点的值,所以中间废掉的空间可以省略,缩点之后用还能用单调队列优化一下。

#include<iostream>#include<cstdio>#include<cstring>#include<iomanip>#include<algorithm>using namespace std;int r,s,t,m,a[10001],b[101],maxx,f[10001],cha[102],q[100001],head=1,tail=0;int cmp(int x,int y){    return x<y;}int main(){    cin>>r>>s>>t>>m;        for(int i=1;i<=m;++i)    cin>>a[i];    if(s==t)    {        int ans=0;        for(int i=1;i<=m;++i)        if(a[i]%s==0) ans++;        cout<<ans;        return 0;    }    sort(a+1,a+m+1,cmp);    for(int i=1;i<=m;++i)    {        cha[i]=a[i]-a[i-1];        if(cha[i]>90) cha[i]=90;    }cha[m+1]=min(r-a[m],100);    memset(a,0,sizeof(a));int l=0;    for(int i=1;i<=m;++i)    {        l+=cha[i];        a[l]=1;    }    l+=cha[m+1];    for(int i=0;i<=l+10;++i)    f[i]=99999;    f[0]=0;int cnt=1;    for(int i=1;i<l+10;++i)     {         if(q[head]<i-t&&head<=tail) head++;         while(f[i-s]<=f[q[tail]]&&head<=tail) tail--;         if(i-s>=0)q[++tail]=i-s;         f[i]=f[q[head]]+a[i];         if(i-s<0) f[i]=999999;     }int ans=999999;    for(int i=l;i<l+10;++i)    if(f[i]<ans) ans=f[i];    cout<<ans;    return 0;}


原创粉丝点击