题解 P5858 【「SWTR-03」Golden Sword】

· · 题解

$\ \ \ \ \ \ \ $考虑到要顺序放置,贡献与当前锅内的原料有关,所以我们考虑将这两个东西加入我们的 dp 式。 $\ \ \ \ \ \ \ $设 $dp_{i,j}$ 为放进 $i$ 原料,且当时正有 $j$ 个原料所得到的最大耐久度。有 dp 方程: $$dp_{i,j}=\max \{dp_{i-1,k}+a_i \times j\}$$ $\ \ \ \ \ \ \ $其中$j-1 \leq k \leq \min \{m,j+s-1\}$。 ```cpp #include<bits/stdc++.h> using namespace std; long long n,m,s,a[5505],dp[5505][5505]; int main(){ scanf("%lld %lld %lld",&n,&m,&s); for(long long i=1;i<=n;++i) scanf("%lld",&a[i]); for(long long i=0;i<=n;++i) for(long long j=0;j<=m;++j) dp[i][j]=-1008600110086001; dp[0][0]=0; for(long long i=1;i<=n;++i) { for(long long j=m;j;--j) { for(long long k=min(m,j+s-1);k>=j-1;--k) { // i-1 k j*a; dp[i][j]=max(dp[i][j],dp[i-1][k]+j*a[i]); } } } long long ans=-1008600110086001; for(long long i=0;i<=m;++i) ans=max(ans,dp[n][i]); printf("%lld",ans); return 0; } ``` $\ \ \ \ \ \ \ $因为这个代码实际上是 $O(nm^2)$ 的。实际因为数据过于水,得到 85。差评。 $\ \ \ \ \ \ \ $考虑到我们枚举 $j \times a_i$ 是一个定值。所以说我们的 dp 方程简化为: $$dp_{i,j}=\max \{dp_{i-1,k}\}+a_i \times j$$ $\ \ \ \ \ \ \ $其中$j-1 \leq k \leq \min \{m,j+s-1\}$。 $\ \ \ \ \ \ \ $我们惊奇地发现,中间 $\max$ 的一坨是可以单调队列优化的! $\ \ \ \ \ \ \ $~~(当然你也可以用线段树,我调爆了)~~ $\ \ \ \ \ \ \ $实际上这就是一道单调队列的板子题吧。。。 ```cpp #include<bits/stdc++.h> using namespace std; long long n,m,s,a[5505],dp[5505][5505],q[5505],pos[5505]; int main(){ scanf("%lld %lld %lld",&n,&m,&s); for(long long i=1;i<=n;++i) scanf("%lld",&a[i]); for(long long i=0;i<=n;++i) for(long long j=0;j<=m;++j) dp[i][j]=-1008600110086001; dp[0][0]=0; for(long long i=1;i<=n;++i) { int l=1,r=1; q[l]=dp[i-1][m]; pos[l]=m; for(long long j=m;j;--j) { while(pos[l]>j+s-1 && l<=r) ++l; while(q[r]<dp[i-1][j-1] && l<=r) --r; pos[++r]=j-1; q[r]=dp[i-1][j-1]; dp[i][j]=q[l]+j*a[i]; } } long long ans=-1008600110086001; for(long long i=0;i<=m;++i) ans=max(ans,dp[n][i]); printf("%lld",ans); return 0; } ```