洛谷-P2285-[HNOI2004]打鼹鼠(dp子序列问题)

[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) (i1,j),(i+1,j),(i,j1),(i,j+1) 四个网格,机器人不能走出整个 n × n n \times n n×n 的网格。游戏开始时,你可以自由选定机器人的初始位置。

现在知道在一段时间内,鼹鼠出现的时间和地点,请编写一个程序使机器人在这一段时间内打死尽可能多的鼹鼠。

输入格式

第一行为 n , m n, m n,m n ≤ 1000 n \le 1000 n1000 m ≤ 10 4 m \le {10}^4 m104),其中 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

这题不能用图的思想去看,如果按照图的思想,不仅要想什么时间走到哪里还要看怎么走,简直就是难爆了。

如果这个机器人可以打完一个地鼠之后能打到另一个地鼠,那么就说明这两个地鼠之间的曼哈顿距离 ∣ x i − x j ∣ + ∣ y i − y j ∣ |xi - xj| + |yi - yj| xixj+yiyj)是小于等于消耗时间的,曼哈顿距离直接反映了在机器人只能上下左右走的条件下两点之间移动要消耗的时间

同时 t i m e time time值是按照递增顺序给出的,所以我们把坐标和时间全部存到一个结构体里,然后把打包后的每个地鼠的属性都当做一段序列中的各个值,这样就转化为了一种子序列问题

之后就可以枚举每一个序列中的元素(起点),然后枚举这个元素前面的所有元素(这里仅仅需要计算从时间靠前的地方到达时间靠后的地方),符合条件的情况就进行状态转移 f [ i ] = m a x ( f [ i ] , f [ j ] + 1 ) f[i] = max(f[i],f[j]+1) f[i]=max(f[i],f[j]+1)

#include<iostream>
#include<vector>
using namespace std;
const int N = 1e4+10;

struct Node {
	int x, y, time;
}a[N];

int f[N];
int n, m;

int main() {
	cin >> n >> m;
	
	for (int i = 1; i <= m; i++)cin >> a[i].time >> a[i].x >> a[i].y;

	for (int i = 1; i <= m; i++) {
		f[i] = 1;
		for (int j = 1; j < i; j++) {
			if (abs(a[i].x - a[j].x) + abs(a[i].y - a[j].y) <= abs(a[i].time - a[j].time)) {
				f[i] = max(f[i], f[j] + 1);
			}
		}
	}
	int res = 0;
	for (int i = 1; i <= m; i++)res = max(res, f[i]);
	cout << res;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值