[NOIpTG2005]过河——[简单DP+路径压缩]

在这里插入图片描述
【题意分析】

naive的dp方程式(dp[i]就是答案):

d p i = min ⁡ s ≤ j ≤ t , i ≥ j { d p i − j + i s s t o n e i } dp_i=\min_{s\leq j\leq t,i\geq j}\{dp_{i-j}+isstone_i\} dpi=sjt,ijmin{dpij+isstonei}

然后L最大有1e9你mle加tle了

很明显中间有大量的无用状态,根据小凯的疑惑那道题我们可以知道间距超过90(还是72?反正差不多,就是t(t-1)),就直接压成90,这样状态数就大大减少了

还有一个注意点就是青蛙跳过L也是可以的,那么就要在 [ L , L + 9 ] [L,L+9] [L,L+9]范围内统计一下最小答案

Code:

//KajKeusaka
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#define INF 2147400000
#define MAXN 100000
using namespace std;

bool flag[MAXN];
int dp[MAXN], pos[MAXN], a[MAXN], len, s, t, n, ans = 0;

inline int read () {
	register int s = 0, w = 1;
	register char ch = getchar ();
	while (! isdigit (ch)) {if (ch == '-') w = -1; ch = getchar ();}
	while (isdigit (ch)) {s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar ();}
	return s * w;
}

int main () {
	len = read (), s = read (), t = read (), n = read ();
	for (register int i = 1; i <= n; i++) pos[i] = read ();
	if (s == t) {
		for (register int i = 1; i <= n; i++) ans += ((pos[i] % s) == 0);
		return printf ("%d\n", ans), 0;
	}
	sort (pos + 1, pos + n + 1), ans = INF;
	for (register int i = 1; i <= n; i++) 
		a[i] = a[i - 1] + min (90, pos[i] - pos[i - 1]), flag[a[i]] = 1;
	len = a[n] + min (len - pos[n], 90) + 9;
	for (register int i = 1; i <= len; i++) dp[i] = INF;
	for (register int i = 1; i <= len; i++)
		for (register int j = s; j <= t; j++)
			if (i >= j) dp[i] = min (dp[i], dp[i - j] + flag[i]);
	for (register int i = len - 9; i <= len; i++) ans = min (ans, dp[i]);
	return printf ("%d\n", ans), 0;
}
/*
10
2 3 5
2 3 5 6 7
*/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值