[HNOI2004] 打鼹鼠
题目描述
鼹鼠是一种很喜欢挖洞的动物,但每过一定的时间,它还是喜欢把头探出到地面上来透透气的。根据这个特点阿牛编写了一个打鼹鼠的游戏:在一个 n × n n \times n n×n 的网格中,在某些时刻鼹鼠会在某一个网格探出头来透透气。你可以控制一个机器人来打鼹鼠,如果 i i i 时刻鼹鼠在某个网格中出现,而机器人也处于同一网格的话,那么这个鼹鼠就会被机器人打死。而机器人每一时刻只能够移动一格或停留在原地不动。机器人的移动是指从当前所处的网格移向相邻的网格,即从坐标为 ( i , j ) (i, j) (i,j) 的网格移向 ( i − 1 , j ) , ( i + 1 , j ) , ( i , j − 1 ) , ( i , j + 1 ) (i-1, j), (i+1, j), (i, j-1), (i, j+1) (i−1,j),(i+1,j),(i,j−1),(i,j+1) 四个网格,机器人不能走出整个 n × n n \times n n×n 的网格。游戏开始时,你可以自由选定机器人的初始位置。
现在知道在一段时间内,鼹鼠出现的时间和地点,请编写一个程序使机器人在这一段时间内打死尽可能多的鼹鼠。
输入格式
第一行为 n , m n, m n,m( n ≤ 1000 n \le 1000 n≤1000, m ≤ 10 4 m \le {10}^4 m≤104),其中 m m m 表示在这一段时间内出现的鼹鼠的个数,接下来的 m m m 行中每行有三个数据 t i m e , x , y \mathit{time}, x, y time,x,y 表示在游戏开始后 t i m e \mathit{time} time 个时刻,在第 x x x 行第 y y y 个网格里出现了一只鼹鼠。 t i m e \mathit{time} time 按递增的顺序给出。注意同一时刻可能出现多只鼹鼠,但同一时刻同一地点只可能出现一只鼹鼠。
输出格式
仅包含一个正整数,表示被打死鼹鼠的最大数目。
样例 #1
样例输入 #1
2 2
1 1 1
2 2 2
样例输出 #1
1
正解
一维 dp 足够了。
一、状态:虽然题目中给出每个鼹鼠出来都会有三个参数 t i m e , x , y time,x,y time,x,y,但是只需要把一个鼹鼠整体看就可以了,也就是 d p [ i ] dp[i] dp[i] 代表打到第 i i i 个鼹鼠最多打的个数。
二、转移:还是需要先初始化的, d p [ i ] = 1 dp[i]=1 dp[i]=1,表示最后会打到这个鼹鼠。然后就是一层循环,遍历 j = 1 j=1 j=1 到 i − 1 i-1 i−1,表示抓第 i i i 个鼹鼠之前被抓住的鼹鼠。接下来就是判断条件,因为需要在下一个鼹鼠来临前打掉,所以需要现在的位置到准备打的鼹鼠的距离 ≤ \le ≤ 两个鼹鼠出现的时间之差,即 if ( ∣ x [ i ] − x [ j ] ∣ + ∣ y [ i ] − y [ j ] ∣ ≤ t i m e [ i ] − t i m e [ j ] ) \operatorname{if}(|x[i]-x[j]|+|y[i]-y[j]|\le time[i]-time[j]) if(∣x[i]−x[j]∣+∣y[i]−y[j]∣≤time[i]−time[j]),这时 d p [ i ] = max ( d [ i ] , d p [ j ] + 1 ) dp[i]=\max(d[i],dp[j]+1) dp[i]=max(d[i],dp[j]+1),多抓一个鼹鼠。
三、答案:最后的答案就是 max ( d p [ 1 ] , d p [ 2 ] , d p [ 3 ] , … , d p [ n ] ) \max(dp[1],dp[2],dp[3],\dots,dp[n]) max(dp[1],dp[2],dp[3],…,dp[n])。
代码
#include <bits/stdc++.h>
//#define int long long
using namespace std;
const int M = 10010;
int t[M],x[M],y[M];
int n,m,mx;
int dp[M];
void solve()
{
cin >> n >> m;
for (int i = 1;i <= m;i++)
cin >> t[i] >> x[i] >> y[i];
for (int i = 1;i <= m;i++)
{
dp[i] = 1;
for (int j = 1;j < i;j++)
if (abs(x[i]-x[j])+abs(y[i]-y[j]) <= t[i]-t[j])
dp[i] = max(dp[i],dp[j]+1);
}
for (int i = 1;i <= m;i++)
mx = max(mx,dp[i]);
cout << mx;
}
signed main()
{
solve();
printf("\n");
return 0;
}