洛谷p1052過河

原題

先想一下思路,由於是區間跳躍,不能用貪心,那麼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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章