← 全部文章

CF559E Gerald and Path 题解

本文目录(3 节)
  1. 题意
  2. 题解
  3. 代码

CF559E Gerald and Path

题意

  • 有 nn 条线段。
  • 每条线段给定其中一端的位置及长度。
  • 求所有线段覆盖的最大长度。
  • n≤100n \le 100。

题解

首先对一端位置排序。

考虑 dp,设 fi,j,pf_{i,j,p} 表示考虑前 ii 条线段,最靠右的线段是第 jj 条,其方向为 pp(00 左 11 右)。

考虑如何转移,从小到大枚举 ii 后面的线段以及它的方向,同时维护枚举过的线段中最靠右的线段以及它的方向。

设线段 jj 在 pp 方向的右端点是 oo;此时枚举到线段 kk,它的方向为 qq,长度为 ll,右端点是 tt;枚举过的线段中最靠右的线段是 xx,它的方向为 yy,右端点是 zz。

那么有转移:

fk,x,y←fi,j,p+min⁡(l,t−o)+z−t f_{k,x,y} \leftarrow f_{i,j,p} + \min(l, t - o) + z - t

时间复杂度 O(n3)\mathcal O(n^3)。

代码

const int N = 107;
int n, ans, f[N][N][2];
pi a[N];

int main() {
	rd(n);
	for (int i = 1; i <= n; i++) rd(a[i].fi), rd(a[i].se);
	sort(a + 1, a + n + 1);
	a[0].fi = -1e9;
	for (int i = 0; i <= n; i++)
		for (int j = 0; j <= i; j++)
			for (int p = 0; p < 2; p++) {
				ans = max(ans, f[i][j][p]);
				int o = a[j].fi + p * a[j].se, mx = -1e9, x, y;
				for (int k = i + 1; k <= n; k++)
					for (int q = 0; q < 2; q++) {
						int t = a[k].fi + q * a[k].se;
						if (t > mx) mx = t, x = k, y = q;
						f[k][x][y] = max(f[k][x][y], f[i][j][p] + min(a[k].se, t - o) + mx - t);
					}
			}
	print(ans);
	return 0;
}

标签:DP

评论

    填写昵称即可留言。评论经站主审核后公开,请勿提交私人信息。

    正在连接评论服务…