[CF1253E]Antenna Coverage 题解

传送门QAQ

Preface

这道题本来我都想好了思路也码出来了,但不知道为啥一直连样例都过不了QAQ

还是太蒻了,只能去看题解啦 >_<

Analysis

不难发现 \(n \le 80,m\le 10^5\) 的数据范围让 \(O(nm)\) 甚至是 \(O(n^2m)\) 的算法变得可行。

结合鬼畜的题目要求,我们珂以尝试用 DP 求解。

\(f(i)\) 表示 \([1,i]\) 范围内全部被覆盖的最小花费。

不难发现,如果加入一个 \((0,0)\) 的点,那么答案也不会产生任何变化。

所以我们珂以让所有 \(f(i)\) 初始值为 \(i\)

然后考虑转移:如果 \(f(i)\) 本来就被某个初始区间覆盖,那么珂以让 \(f(i) \gets f(i-1)\)

否则,让本来在 \(i\) 之前且覆盖不到 \(i\) 的某个点覆盖它,转移一下就好了。

但为什么不让 \(i\) 之后的点覆盖它呢?

我们发现,点 \(m\) 肯定是要用 \(m\) 之前的点覆盖,那么这个时候,\(m\) 前的某些地方肯定也能被覆盖到。

相当于间接枚举了这种状态。

以上均为口胡,想看严谨证明请去看我参考的 ATS 大神的题解

时间复杂度 \(O(nm)\)

Code

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int n,m;
int a[maxn],c[maxn],f[maxn];
int main() {
	scanf("%d%d",&n,&m);
	for(int i = 1;i <= n;++ i)scanf("%d %d",&a[i],&c[i]);
	f[0] = 0;
	for(int i = 1;i <= m;++ i) {
		f[i] = i;
		for(int j = 1;j <= n;++ j) {
			if(a[j] + c[j] >= i&&a[j] - c[j] <= i) {
				f[i] = f[i - 1];
				break ;
			}
		}
		for(int j = 1;j <= n;++ j) {
			if(a[j] + c[j] < i) {
				f[i] = min(f[i] , f[max(0 , (a[j] << 1) - i - 1)] + i - (a[j] + c[j]));
			}
		}
	}
	printf("%d\n",f[m]);
	return 0;
}

完结撒花✿✿ヽ(°▽°)ノ✿

posted @ 2022-07-02 13:30  ImALAS  阅读(38)  评论(0编辑  收藏  举报