【DP】ABC273F Hammer 2 题解

发布时间 2023-10-05 22:37:06作者: Pengzt

ABC273F

一道比较板的区间 \(\text{dp}\)

先对坐标离散化,令离散化数组为 \(v\)

\(f_{i,j}\) 表示能走到区间 \([v_i,v_j]\) 的最短路程,显然 \(f\) 数组初始为 \(inf\)

但发现这样无法转移,可以再增加一维 \(k \in \{0,1\}\),表示此时在 \([v_i,v_j]\)\(v_i/v_j\) 处。

则有转移方程:

\[f_{i-1,j,0} = \min\{f_{i-1,j,0}, f_{i,j,0}+v_i-v_{i-1}, f_{i,j,1}+v_j-v_{i-1}\} \]

\[f_{i,j+1,1} = \min\{f_{i,j+1,1}, f_{i,j,0}+v_{j+1}-v_i, f_{i,j,1}+v_{j+1}-v_j\} \]

代码:

const int N = 1.5e3 + 5;
int n, x;
int a[N], b[N], v[N << 1], pos[N << 1];
ll f[N << 1][N << 1][2];

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cin >> n >> x;
	int cnt = 0;
	v[++cnt] = 0, v[++cnt] = x;
	for (int i = 1; i <= n; i++) std::cin >> a[i], v[++cnt] = a[i];
	for (int i = 1; i <= n; i++) std::cin >> b[i], v[++cnt] = b[i];
	std::sort(v + 1, v + cnt + 1);
	cnt = std::unique(v + 1, v + cnt + 1) - (v + 1);
	for (int i = 1; i <= n; i++) {
		int k1 = std::lower_bound(v + 1, v + cnt + 1, a[i]) - v, k2 = std::lower_bound(v + 1, v + cnt + 1, b[i]) - v;
		a[i] = k1, b[i] = k2, pos[a[i]] = i;
	}
	int s = std::lower_bound(v + 1, v + cnt + 1, 0) - v, t = std::lower_bound(v + 1, v + cnt + 1, x) - v;
	memset(f, 0x3f, sizeof(f));
	f[s][s][0] = f[s][s][1] = 0;
	for (int l = 1; l <= cnt; l++)
		for (int i = 1; i <= cnt - l + 1; i++) {
			int j = i + l - 1;
			if (i > 1) {
				int p = pos[i - 1];
				if (!p || (i <= b[p] && b[p] <= j))
					f[i - 1][j][0] = std::min(f[i - 1][j][0], std::min(f[i][j][0] + v[i] - v[i - 1], f[i][j][1] + v[j] - v[i - 1]));
			}
			if (j < cnt) {
				int p = pos[j + 1];
				if (!p || (i <= b[p] && b[p] <= j))
					f[i][j + 1][1] = std::min(f[i][j + 1][1], std::min(f[i][j][0] + v[j + 1] - v[i], f[i][j][1] + v[j + 1] - v[j]));
			}
		}
	ll ans = f[0][0][0];
	for (int i = 1; i <= t; i++)
		for (int j = t; j <= cnt; j++)
			ans = std::min(ans, std::min(f[i][j][0], f[i][j][1]));
	std::cout << (ans == f[0][0][0] ? -1 : ans) << "\n";
	return 0;
}