题解
这道题\(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;
}