CF1427C The Hard Work of Paparazzi题解

CF1427C The Hard Work of Paparazzi

题意:有一个r*r(r≤500)的地图,起始位置是(1,1),有n(n≤1e5)个人在特定时间会在某个点出现一次(按照时间升序给出),问最多能和多少个人相遇。

解法:这道题的思路很新颖,我一开始一直考虑bfs,却没办法写出来,因为n太大了。完全没有想到是线性dp 。刚开始听说这题正解是dp的时候,就觉得像是n ^ 2的循环(dp[i]代表到第i个时间时,前面最多能遇到多少人),但是明显会超时,这里要发现一个特点,如果是n ^ 2的那种循环,会发现r根本没有用处,其实就是用r去优化第二重循环。首先,两个点之间的距离最多是2r,且时间严格升序,那么i一定能从[0,i-2r]转移过来,最大必然是在[i-4r,i-2r]之间(我考虑原因应该是这里的值都是由之前的值更新而来的,因而可以缩减到这个范围),但对于[i-2r,i-1]这一部分就需要判断啦(以下代码也判断了[i-4r,i-2r]的)。这样的话,n ^ 2的复杂度能优化到n * r,跟昨天那道题目有点像。
在这里插入图片描述
感谢评论区大佬指出呀~

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5+10;
int dp[N];
struct xx {
    
    
	int t, x, y;
}a[N];
int dis(xx a1, xx a2) {
    
    
	return abs(a1.x-a2.x)+abs(a1.y-a2.y);
}
int main() {
    
    
	memset(dp, -1, sizeof dp);
	int r, n;
	scanf("%d%d", &r, &n);
	a[0].x = 1, a[0].y = 1; dp[0] = 0;
	for(int i = 1; i <= n; ++i) scanf("%d%d%d", &a[i].t, &a[i].x, &a[i].y);
	for(int i = 1; i <= n; ++i) {
    
    
		for(int j = max(0, i-1-r*4); j < i; ++j) {
    
    
			if(dp[j] != -1 && a[i].t - a[j].t >= dis(a[i], a[j])) 
				dp[i] = max(dp[i], dp[j]+1);
		}
	}
	int ans = 0;
	for(int i = 1; i <= n; ++i) ans = max(ans, dp[i]);
	printf("%d\n", ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43408978/article/details/109010714