[题解]CF234F Fence

CF234F Fence ~ Codeforces

\(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;
}
posted @ 2025-08-26 13:30  Sinktank  阅读(18)  评论(0)    收藏  举报
★CLICK FOR MORE INFO★ TOP-BOTTOM-THEME
Enable/Disable Transition
Copyright © 2023 ~ 2025 Sinktank - 1328312655@qq.com
Illustration from 稲葉曇『リレイアウター/Relayouter/中继输出者』,by ぬくぬくにぎりめし.