线性DP—洛—打鼹鼠
P2285 [HNOI2004] 打鼹鼠
题目描述
鼹鼠是一种很喜欢挖洞的动物,但每过一定的时间,它还是喜欢把头探出到地面上来透透气的。
根据这个特点阿牛编写了一个打鼹鼠的游戏:在一个 \(n \times n\) 的网格中,在某些时刻鼹鼠会在某一个网格探出头来透透气。
你可以控制一个机器人来打鼹鼠,如果 \(i\) 时刻鼹鼠在某个网格中出现,而机器人也处于同一网格的话,那么这个鼹鼠就会被机器人打死。
而机器人每一时刻只能够移动一格或停留在原地不动。机器人的移动是指从当前所处的网格移向相邻的网格,即从坐标为 \((i, j)\) 的网格移向 \((i-1, j), (i+1, j), (i, j-1), (i, j+1)\) 四个网格,机器人不能走出整个 \(n \times n\) 的网格。
游戏开始时,你可以自由选定机器人的初始位置。
现在知道在一段时间内,鼹鼠出现的时间和地点,请编写一个程序使机器人在这一段时间内打死尽可能多的鼹鼠。
输入格式
第一行为 \(n, m\ (1 \le n \le 10^3, 1 \le m \le 10^4)\),其中 \(m\) 表示在这一段时间内出现的鼹鼠的个数。
接下来的 \(m\) 行中每行有三个数据 \(t, x, y\ (1 \le t \le 2.5 \times 10^7, 1 \le x,y \le n)\),表示在游戏开始后 \(t\) 个时刻,在第 \(x\) 行第 \(y\) 个网格里出现了一只鼹鼠。
\(t\) 按不降的顺序给出。
注意同一时刻可能出现多只鼹鼠,但同一时刻同一地点只可能出现一只鼹鼠。
输出格式
仅包含一个非负整数,表示被打死鼹鼠的最大数目。
输入输出样例 #1
输入 #1
2 2
1 1 1
2 2 2
输出 #1
1
刚开始想法
错误转移状态代码:
点击查看代码
for(int i = 1;i <= m;i++)
{int temp = 0;for(int j = 1;j < i;j++){int dis1 = a[i].t-a[j].t; //a数组存了鼹鼠出现的时间和坐标int dis2 = abs(a[i].x-a[j].x) + abs(a[i].y-a[j].y);if(dis1 >= dis2 && dis1%2 == dis2%2){temp = max(temp,dp[a[j].x][a[j].y]);}}dp[a[i].x][a[i].y] = max(temp+1,dp[a[i].x][a[i].y]); ans = max(ans, dp[a[i].x][a[i].y]);
}
一开始认为是网格dp,但由于网格数据大,鼹鼠数多,后想到只枚举出现的鼹鼠,跟新相应网格的dp。一开始没看题,机器人可以不动,认为要加时间距离和曼哈顿距离奇偶性相同的条件。而且我想网格最大dp值的时间是最新跟新的时间,因为我的内层是时间从小到大,每次只需要看最近的时间即可。这样前面每个鼹鼠时间信息无法保存,导致所有同一点鼹鼠不同时间却共享一个最大dp值。我前面小的时间点也是最大的dp值,会跟新最大值temp,但其实这个网格最大dp是后面的时间跟新来的,而后面的时间可能太大,时间距离小小于曼哈顿距离可能无法跟新当前时间dp值。
至于为什么一开始认为思路没问题,就是老想着自己的状态转移方程没错,但是这个同一位置相应小时间对应的dp值错了没想到。
正确做法
有数据范围,想到遍历鼹鼠信息进行dp是对的,但不该是网格dp,而是线性dp,dp[i]表示遍历第i只鼹鼠的最大值。我的时间,坐标信息在结构体里保存的都有,完全没必要用二维来存坐标信息反而忽略了时间信息。
正确代码:
点击查看代码
#include <bits/stdc++.h>
using namespace std;
struct ty
{int t,x,y;
}a[10010];
int dp[10010]; //第i只鼹鼠最大值
int n,m,ans;
int main()
{cin>>n>>m;for(int i = 1;i <= m;i++) {int t,x,y;cin>>t>>x>>y;a[i] = {t,x,y};dp[i] = 1; //赋初值,机器人第一步任意达到}for(int i = 1;i <= m;i++){int temp = 0;for(int j = 1;j < i;j++){int dis1 = a[i].t-a[j].t;int dis2 = abs(a[i].x-a[j].x) + abs(a[i].y-a[j].y);if(dis1 >= dis2){temp = max(temp,dp[j]);}}dp[i] = temp+1; ans = max(ans, dp[i]);}cout<<ans;return 0;
}
反思
这题具有迷惑性,看到坐标就像着用二维dp,其实没必要,有大量的位置是没用信息,只关注鼹鼠的时间位置,配合曼哈顿距离计算即可。