题解 P2285 【[HNOI2004]打鼹鼠】

· · 题解

显而易见,本题需要用DP解决。
为更好的理解,读完题后,就自己去造了个数据——

4 5
1 1 1
2 4 3
3 2 3
4 4 1
5 1 4

如图所示

在指定的时间内可以到达的有——
1 -> 3 , 1 -> 4 , 1 -> 5 , 2 -> 4 , 2 -> 5 , 3 -> 5。

STEP 1

易发现,若 A 能到 B , B 能到 C ,那么 A 一定能到 C 。
所以,在进行预处理之后,用类似于 FLoyd 的松弛操作便能达成我们的目的。
但是此时,O(N^3) 的时间复杂度与 10000 的二维数组将时间和空间都爆掉了。。。

STEP 2

看着看着,我发现若将预处理第一维进行倒序循环,便可以将时间复杂度降到 O(N^2) ,本意就是若 C 能到 B , B 能到 A ,那么 A 便能经过 3 个点。
现在,只要将dp降到一维,就可以完美AC了!

STEP 3

秃然发现突破点——不管 dp[A] 现在是多少,只要 A 能达到 B 那么

降维成功!此时答案只要取最大值就好了。 贴代码 ```cpp #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int M = 1e4+5; int n,m,dp[M],ans; struct node{ int t,x,y; }a[M];//存位置结构体 int main() { cin >> n >> m; for ( int i = 1;i <= m; i++ ) { dp[i] = 1;//开始,所有位置都能达到它自己 scanf ("%d%d%d",&a[i].t,&a[i].x,&a[i].y); } for ( int i = m; i > 1; i-- ) for ( int j = i-1; j >= 1; j-- ) { if (a[i].t-a[j].t>=abs(a[i].x-a[j].x)+abs(a[i].y-a[j].y)) { dp[j] = max(dp[i]+1,dp[j]); //若在规定时间内i能达到j,dp更新 } } for ( int i = 1; i <= m; i++ ) { ans = max(dp[i],ans); //结果取最大值,达到点最多 } printf ("%d",ans);//输出 return 0; } ``` ###### ACCEPT!