[题解]CF234F Fence
令 \(f[i][j][k][l=0/1]\) 为给前 \(i\) 个栅栏涂色,红色面积为 \(j\),绿色面积为 \(k\),第 \(i\) 个栅栏涂红 / 绿色的最小难看值。
显然有转移:
\[f[i][j][k][l]=\begin{cases}
\min\Big(f[i-1][j-h[i]][k][0],f[i-1][j-h[i]][k][1]+\min(h[i],h[i-1])\Big)&l=0,j\ge h[i]\\
\min\Big(f[i-1][j][k-h[i]][1],f[i-1][j][k-h[i]][0]+\min(h[i],h[i-1])\Big)&l=1,k\ge h[i]
\end{cases}
\]
然而这样时间空间都会炸。
不过我们发现,当 \(i,j\) 确定的情况下,\(k\) 是可以被计算出来的,因此可以砍掉 \(k\) 这一维,可以通过。
时间复杂度为 \(O(nV)\),其中 \(V\) 与 \(a,b\) 同阶。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=205,V=4e4+5;
int n,a,b,s[N],h[N],f[N][V][2],ans=1e9;
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
cin>>n>>a>>b;
for(int i=1;i<=n;i++) cin>>h[i],s[i]=s[i-1]+h[i];
h[0]=1e9;
memset(f,0x3f,sizeof f);
f[0][0][0]=f[0][0][1]=0;
for(int i=1;i<=n;i++){
for(int j=max(0,s[i]-b);j<=min(a,s[i]);j++){
if(j>=h[i]) f[i][j][0]=min(f[i-1][j-h[i]][0],f[i-1][j-h[i]][1]+min(h[i],h[i-1]));
f[i][j][1]=min(f[i-1][j][1],f[i-1][j][0]+min(h[i],h[i-1]));
}
}
for(int i=0;i<=a;i++) ans=min({ans,f[n][i][0],f[n][i][1]});
cout<<(ans==1e9?-1:ans)<<"\n";
return 0;
}
浙公网安备 33010602011771号