AtCoder Beginner Contest 219 H

假设我们按照蜡烛的坐标从小到大排序,那么我们每到达一个蜡烛,肯定要熄灭它。

所以,在任意时刻我们走过的蜡烛都是一个区间。

按坐标正负分成2部分,分别按到0的距离排序。我们设dp(l,r,0/1)表示熄灭了负数坐标蜡烛的前l个,正数坐标的前r个,当前在最左侧还是最右侧。

转移就可以枚举下一次走到负数坐标的l+1项还是整数坐标的r+1项。

但有一个问题:dp(l,r,0/1)是维护时间,还是维护目前熄灭蜡烛的最大长度?

发现两者一个最优,另一个未必最优。我们将任何一个放入dp中代表一个维度,此时就可以了,但状态数太大了。

2种解决方案。

我们设state.time表示方案state所需的时间,state.length表示目前熄灭蜡烛的长度和。

我们一个dp中的元素可以存若干个状态,但是若存在状态x,y,使得x.time<y.time并且x.length>y.length,那么y就可以不要了。(因为x的时间比y小,而熄灭蜡烛的长度比y大)

然而这样剩余的状态还是太多。考虑使用剪枝,具体的,若存在状态x,y,若y.lengthn(y.timex.time)>x.length,则x可以不要。

时间复杂度玄学,不过是很快的,比O(n3)还要优秀。

第二种方案:我们发现可以维护dp(l,r,k,0/1)l,r,0/1和之前的一样,而k的意思是,我们在剩下的蜡烛中还有k个是在燃烧完被熄灭的。

那么转移的时候,假设到下一个所花费的时间是t,那么在t时间内,这k个蜡烛的长度都会减1,故这k个蜡烛的长度共减去了kt。到下一个蜡烛时,我们有2种选择:它在这k个蜡烛中,则将dp(l,r,k,p)+len转移到dp(l,r,k1,p),否则将dp(l,r,k,p)转移到dp(l,r,k,p)

那么有一个问题,万一这k个蜡烛中有的燃烧成了负数呢?

可以发现,若dp(l,r,k,p)中有蜡烛燃烧成负数,那就会对答案造成一个负的贡献,不妨抛掉这些蜡烛,也就是取dp(l,r,k1,p)会更优,所以不必考虑。

时间复杂度为O(n3)

#include<bits/stdc++.h>
using ll=long long;
const int maxn=305;
int n,m1,m2;
ll f[maxn][maxn][maxn][2];
bool vis[maxn][maxn][maxn][2];
std::pair<ll,ll> a[maxn],b[maxn];
ll dfs(int l,int r,int k,int where) {	
	if(k==0) return 0;
	if(vis[l][r][k][where]) return f[l][r][k][where];
	ll &ret=f[l][r][k][where]; ret=-1e18;
	vis[l][r][k][where]=1;
	ll now,nxt;
	if(where==0) now=a[l].first;
	else now=b[r].first;
	for(int i=0;i<2;i++) {
		int l_=l,r_=r,len;
		if(i==0) nxt=a[l+1].first,len=a[l+1].second,l_++; 
		else nxt=b[r+1].first,len=b[r+1].second,r_++;
		ll dis=abs(now-nxt);
		if(l_>m1||r_>m2) continue;
		ret=std::max(ret,dfs(l_,r_,k,i)-k*dis);
		ret=std::max(ret,dfs(l_,r_,k-1,i)+len-k*dis);
	}
	return ret;
}
int main() {
	scanf("%d",&n);
	for(int i=1;i<=n;i++) {
		ll ix,ia;
		scanf("%lld%lld",&ix,&ia);
		if(ix<0) a[++m1]=std::make_pair(ix,ia);
		else b[++m2]=std::make_pair(ix,ia);
	}
	a[0]=std::make_pair(0ll,0ll),b[0]=std::make_pair(0ll,0ll); 
	std::sort(a+1,a+m1+1,std::greater<std::pair<ll,ll>>()); 
	std::sort(b+1,b+m2+1);
	ll ans=0;
	for(int i=1;i<=n;i++)
		ans=std::max(ans,dfs(0,0,i,0));
	printf("%lld\n",ans);
	return 0;
}
posted @   Nastia  阅读(35)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示