[BZOJ 1207] [HNOI 2004] 打鼹鼠 【DP】

题目链接:BZOJ - 1207

题目分析

每一次打鼹鼠一定是从上一次打某只鼹鼠转移过来的,从打第 j 只鼹鼠能不能转移到打第 i 只鼹鼠,算一下曼哈顿距离和时间差就知道了。

那么就有一个 DP ,用 f[i] 表示打完第 i 只鼹鼠时最多打了多少只鼹鼠,然后 f[i] 可以由 f[1] .. f[i-1] 转移,类似于最长上升子序列。

然而这道题不能像最长上升子序列一样二分优化或树状数组优化,只能加一个判断 Maxf[] 都不够大就退出的优化。见代码。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

const int MaxN = 10000 + 5;

int n, Ans;
int f[MaxN], Maxf[MaxN], x[MaxN], y[MaxN], t[MaxN]; 

inline int Abs(int x) {return x < 0 ? -x : x;}

int main() 
{
	int Fun;
	scanf("%d%d", &Fun, &n);
	Ans = 0;
	for (int i = 1; i <= n; ++i) {
		scanf("%d%d%d", &t[i], &x[i], &y[i]);
		f[i] = 1;
		for (int j = i - 1; j >= 1; --j) {
			if (Maxf[j] + 1 <= f[i]) break;
			if (f[j] + 1 > f[i] && (Abs(x[i] - x[j]) + Abs(y[i] - y[j]) <= t[i] - t[j])) 
				f[i] = f[j] + 1;
		}
		Maxf[i] = Maxf[i - 1];
		if (f[i] > Maxf[i]) Maxf[i] = f[i];
		if (f[i] > Ans) Ans = f[i];
	}
	printf("%d
", Ans);
	return 0;
}

  

原文地址:https://www.cnblogs.com/JoeFan/p/4249349.html