过河(状压dp

过河(状压dp

luogu P1052
过河(状压dp_第1张图片
最初想法,但是l太大必TLE

int l,s,t,m;
map<int,int> dp,mp;
//int dp[maxn],mp[maxn];
int main(){
    l=ird();
    s=ird();t=ird();m=ird();
    for(int i=1;i<=m;i++){
        mp[ird()]=1;
    }
    for(int i=0;i<=l+t;i++){
        dp[i]=1e9+10;
    }
    dp[0]=0;
    int ans=1e9+10;
    for(int i=1;i<=l+t;i++){
        for(int j=s;j<=min(i,t);j++){
            dp[i]=min(dp[i],dp[i-j]+mp[i]);
        }
        if(i>=l)
            ans=min(ans,dp[i]);
    }
    cout<<ans<<endl;
    return 0;
}

因为数据大小l为1e9,石子分布点只有100,可以把中间的0压缩

int mod=2520;//2520是2~10的最小公倍数
    for(int i=1;i<=m;i++){
        if(mp[i]-mp[i-1]>mod){
            d+=mp[i]-mp[i-1]-(mp[i]-mp[i-1])%mod;
        }
        a[mp[i]-d]=1;
    }

记得最后要把l的值改成最后一个石子压缩后的大小(RE到si

int l,s,t,m;
int dp[maxn],mp[maxn],a[maxn];
int main(){
    l=ird();
    s=ird();t=ird();m=ird();
    for(int i=1;i<=m;i++){
        mp[i]=ird();
    }
    sort(mp+1,mp+1+m);
    int d=0;
    int mod=2520;
    for(int i=1;i<=m;i++){
        if(mp[i]-mp[i-1]>mod){
            d+=mp[i]-mp[i-1]-(mp[i]-mp[i-1])%mod;
        }
        a[mp[i]-d]=1;
    }
    for(int i=0;i<=maxn;i++){
        dp[i]=1e9+10;
    }
    dp[0]=0;
    int ans=1e9+10;
    l=mp[m]-d;
    for(int i=1;i<=l+t;i++){
        for(int j=s;j<=min(i,t);j++){
            dp[i]=min(dp[i],dp[i-j]+a[i]);
        }
        if(i>=l)
            ans=min(ans,dp[i]);
    }
    cout<<ans<<endl;
    return 0;
}

你可能感兴趣的:(DP)