Live2D

Solution -「ABC 219H」Candles

Description

  Link.

  有 n 支蜡烛,第 i 支的坐标为 xi,初始长度为 ai,每单位时间燃烧变短 1 直到长度为 0。你从 0 位置出发,每次可以向左或向右走 1 单位,走到一个蜡烛的位置可以吹熄蜡烛。求最多能保留的蜡烛长度之和。

  n300

Solution

  和 甲虫 这题比较像,可以说是相同思路的不同实现方法。问题的核心自然是费用提前计算,我们需要知道想要吹熄的蜡烛数量才能计算当前行动一步带来的总长度损失。注意到 n 较小,可以直接把这一信息记入状态。

  具体地,加入一支 xn+1=an+1=0 的蜡烛,设按坐标排序后该蜡烛的下标为 p。令 f(l,r,0/1,k) ([l,r]p,k[0,n]) 表示当前经过了区间 [l,r] 内的蜡烛位置,停留在 l/r,还希望在这个区间以外获得 k 支蜡烛。通过忽略“蜡烛长度非负”这一限制,把最大化最大值转化成最大化任意值,可以轻松 DP 求解。复杂度 O(n3)

Code

/*~Rainybunny~*/

#include <bits/stdc++.h>

#define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )

typedef long long LL;
typedef std::pair<int, int> PII;
#define fi first
#define se second

const int MAXN = 300;
const LL LINF = 1ll << 60;
int n;
LL f[MAXN + 5][MAXN + 5][2][MAXN + 5];
PII cdl[MAXN + 5];

inline LL dabs( const LL u ) { return u < 0 ? -u : u; }
inline void chkmax( LL& u, const LL v ) { u < v && ( u = v ); }

int main() {
	scanf( "%d", &n ), ++n;
	rep ( i, 2, n ) scanf( "%d %d", &cdl[i].fi, &cdl[i].se );
	
	std::sort( cdl + 1, cdl + n + 1 );
	int p = std::lower_bound( cdl + 1, cdl + n + 1, PII( 0, 0 ) ) - cdl;
	
	rep ( i, 1, n ) rep ( j, i + 1, n ) rep ( t, 0, 1 ) rep ( k, 0, n ) {
		f[i][j][t][k] = -LINF;
	}
	rep ( i, 0, n ) f[p][p][0][i] = 0;
	LL ans = 0;
	rep ( len, 0, n - 1 ) {
		for ( int i = 0, l, r; i <= len; ++i ) {
			if ( ( l = p - i ) <= 0 || ( r = p + len - i ) > n ) continue;
		  	int x[2] = { cdl[l].fi, cdl[r].fi };
			rep ( t, 0, 1 ) {
				rep ( k, 0, n ) {
					LL cur = f[l][r][t][k];
					if ( cur == -LINF ) continue;
					if ( !k ) { chkmax( ans, cur ); continue; }
					if ( l > 1 ) {
						chkmax( f[l - 1][r][0][k - 1], cur + cdl[l - 1].se
						  - dabs( x[t] - cdl[l - 1].fi ) * k );
						chkmax( f[l - 1][r][0][k], cur
						  - dabs( x[t] - cdl[l - 1].fi ) * k );
					}
					if ( r < n ) {
						chkmax( f[l][r + 1][1][k - 1], cur + cdl[r + 1].se
						  - dabs( x[t] - cdl[r + 1].fi ) * k );
						chkmax( f[l][r + 1][1][k], cur
						  - dabs( x[t] - cdl[r + 1].fi ) * k );
					}
				}
			}
		}
	}
	printf( "%lld\n", ans );
	return 0;
}

posted @   Rainybunny  阅读(65)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示