CF1427C Solution

题目链接

题解

这道题\(10^5\)的数据范围显然不可以用图论,因此是贪心和dp中的一种,可是在单个子问题中最优的方案不一定满足全局最优,所以只能用dp。

\(dp[i]\)表示前\(i\)个人中可以拍下的最大人数(必须选择第\(i\)个人)。转移则在所有可以到达\(i\)的点中选取\(dp\)值最大即可,转移方程:\(dp[i]=max(dp[i],dp[j]+1)\quad\quad (0\le j<i,dis(i,j)<=t[i]-t[j] )\)

显然,这个方程的时间复杂度为\(O(n^2)\),会超时。观察这个\(r\cdot r\)的网格图,可以发现从一个点到另一个点的最长路径为\(2r-2\)(从\((1,1)\)\((r,r)\))。所以我们只用枚举\(t[i]-t[j]<2r-2\)\(j\),再之前的\(j\)一定可以到达\(i\)。另设\(ans[j]\)记录前\(j\)人可以不选第\(j\)个人时的最大\(dp\)值,便可\(O(1)\)求出满足\(t[i]-t[j]>=2r-2\)\(j\)的最大值。

AC代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int x[N],y[N],t[N],dp[N],ans[N];
int main()
{
	int r,n;
	scanf("%d%d",&r,&n);
	for(int i=1;i<=n;i++) scanf("%d%d%d",&t[i],&x[i],&y[i]);
	memset(dp,-0x3f,sizeof(dp));
	t[0]=0,x[0]=1,y[0]=1,dp[0]=0,ans[0]=0;
	for(int i=1;i<=n;i++)
	{
		int j;
		for(j=i-1;j>=0;j--)
		{
			if(t[i]-t[j]>=(2*r-2)) break;
			if(abs(x[i]-x[j])+abs(y[i]-y[j])<=t[i]-t[j]) dp[i]=max(dp[i],dp[j]+1);
		} 
		if(j>=0) dp[i]=max(dp[i],ans[j]+1); 
		ans[i]=max(ans[i-1],dp[i]);
	}
	printf("%d",ans[n]);
	return 0;
}
posted @ 2020-12-20 10:46  violet_holmes  阅读(54)  评论(0编辑  收藏  举报