JOISC 2014 邮戳拉力赛(基础DP)

Posted paulliant

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JOISC 2014 邮戳拉力赛(基础DP)相关的知识,希望对你有一定的参考价值。

题意

https://loj.ac/problem/2878

思路

真的神仙题,想到就很好写,想不到就写不出来。

肯定只能一个一个邮戳按顺序分析。首先,将取一枚邮戳的路径分为四种:

  • 上行 ( ightarrow) 邮戳台 ( ightarrow) 上行 简称路径 ((U,V))
  • 上行 ( ightarrow) 邮戳台 ( ightarrow) 下行 简称路径 ((U,E))
  • 下行 ( ightarrow) 邮戳台 ( ightarrow) 下行 简称路径 ((D,E))
  • 下行 ( ightarrow) 邮戳台 ( ightarrow) 上行 简称路径 ((D,V))

取一枚邮戳也就这四种路径。

但我们发现,路径 ((D,V)) 的出现前提是有路径 ((U,E)) 在前面出现过,也就是说到任意一个点路径 ((U,E)) 的条数总是多余路径 ((D,V)) 。也是说,我们可以将 ((U,E)) 的条数减 ((D,V)) 的条数当 ( ext{dp}) 的第二维,也就是还未抵消的 ((U,E)) 路径。另外 ((D,V)) 路径出现的条件为至少有一个还未抵消的 ((U,E)) 路径。

那么转移就是上述的四种,一个 (O(n^3)) 的暴力很快就能出来了

chk_min(dp[i][j],dp[i-1][j]+u+v);
if(j>0)chk_min(dp[i][j],dp[i-1][j]+d+e);
FOR(k,1,j)chk_min(dp[i][j],dp[i-1][j-k]+(d+v)*k);
FOR(k,1,n-j)chk_min(dp[i][j],dp[i-1][j+k]+(u+e)*k);
dp[i][j]+=(ll)T*(2*j+1);    //计算j个(D,V)路径的贡献 

不难发现后面两维可以直接前后缀优化,或者背包转移,复杂度就优化至 (O(n^2)) 了。

代码

#include<bits/stdc++.h>
#define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
#define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
using namespace std;
template<typename T,typename _T>inline bool chk_min(T &x,const _T y){return y<x?x=y,1:0;}
template<typename T,typename _T>inline bool chk_max(T &x,const _T y){return x<y?x=y,1:0;}
typedef long long ll;
const int N=3005;
ll dp[N][N],f[N],g[N];
int n,T;

int main()
{
    scanf("%d%d",&n,&T);
    memset(dp,0x3f,sizeof(dp));
    dp[0][0]=0;
    FOR(i,1,n)
    {
        int u,v,d,e;
        scanf("%d%d%d%d",&u,&v,&d,&e);
        FOR(j,0,n)f[j]=g[j]=dp[i-1][j];
        FOR(j,1,n)chk_min(f[j],f[j-1]+(d+v));
        DOR(j,n-1,0)chk_min(g[j],g[j+1]+(u+e));
        FOR(j,0,n)
        {
            chk_min(dp[i][j],dp[i-1][j]+u+v);
            if(j>0)chk_min(dp[i][j],dp[i-1][j]+d+e);
//          FOR(k,1,j)chk_min(dp[i][j],dp[i-1][j-k]+(d+v)*k);
//          FOR(k,1,n-j)chk_min(dp[i][j],dp[i-1][j+k]+(u+e)*k);
            if(j>0)chk_min(dp[i][j],f[j-1]+(d+v));
            if(j<n)chk_min(dp[i][j],g[j+1]+(u+e));
            dp[i][j]+=(ll)T*(2*j);
        }
    }
    printf("%lld
",dp[n][0]+(n+1)*T);
    return 0;
}

以上是关于JOISC 2014 邮戳拉力赛(基础DP)的主要内容,如果未能解决你的问题,请参考以下文章

[JOISC2014]たのしい家庭菜園

JOISC2020 自闭记

LOJ 3276 JOISC 2020 Day2 遗迹 题解 (计数DP)

[JOISC2014]水筒

[JOISC2014]バス通学

[JOISC2014]スタンプラリー