码迷,mamicode.com
首页 > 其他好文 > 详细

【每日一题】27. 过河 (DP + 离散化)

时间:2021-05-24 12:38:52      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:cout   sort   青蛙跳   跳过   题目   lock   const   表示   int   

补题链接:Here

算法涉及:DP + 离散化

\(l\) 的范围太大,无法作为数组下标,所以先离散化,再DP。两点间的距离d大于t时,一定可以由 \(d\ \%\ t\) 跳过来,所以最多只需要t+d%t种距离的状态就可以表示这两个石子之间的任意距离关系。这样就把题目中的 \(10^9\) 压缩成了\(2*t*m\) 最多不超过 \(2000\) ,然后就可以放心大胆地用DP了。不过要注意题目中的“当青蛙跳到或跳过坐标为L的点时,就算青蛙已经跳出了独木桥”,所以DP的终点是一个范围而非确切的一个点,最后还要在这个范围内取最小值。

using ll = long long;
const int N = 1e6 + 10;
const ll inf = 0x3f3f3f3f;
ll dp[N], a[N], vis[N];
void solve() {
	int l, s, t, m;
	cin >> l >> s >> t >> m;
	for (int i = 1; i <= m; ++i)cin >> a[i];
	sort(a + 1, a + 1 + m);
	a[0] = 0, a[m + 1] = l;
	int tmp = 0;
	for (int i = 1; i <= m + 1; ++i) {
		//这里一定要在取模后加t,否则会WA
		if (a[i] - a[i - 1] > t)tmp += (a[i] - a[i - 1]) % t + t;
		else tmp += a[i] - a[i - 1];
		vis[tmp] = 1; //表示此处有石子
	}
	memset(dp, 0x3f, sizeof(dp));
	dp[0] = 0;
	for (int i = 1; i <= tmp + 100; ++i)
		for (int j = s; j <= t; ++j)
			if (i >= j)dp[i] = min(dp[i], dp[i - j] + vis[i]);
	ll ans = inf;
	//终点可能的范围,稍微写大点·
	for (int i = tmp; i <= tmp + 100; ++i)
		ans = min(ans, dp[i]);
	cout << ans;
}

【每日一题】27. 过河 (DP + 离散化)

标签:cout   sort   青蛙跳   跳过   题目   lock   const   表示   int   

原文地址:https://www.cnblogs.com/RioTian/p/14773808.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!