题意:
一只足够聪明的青蛙要过河 它每次最多跳L米 河宽m米 河中有n个石头 你可以任意的添加石头 问 青蛙最多跳几次
思路:
明显的考验想法 题的方向不是乱搞题就是贪心题
首先我们明确 想要次数最多一定要每次跳的最短 但是不能忽略青蛙足够聪明 因此想到可以每2步跳L+1米
考虑到河中本来就有一些石头 所以每次跳之前要先判断是不是能跳到石头上 如果能就不需要加石头 因为加石头近了青蛙不理你 加远了青蛙跳得远就不符合次数最多
最后就是本题最难想的点 每一步的长度受上一步的长度限制 那么就需要记一个last 同时每次少跳一个L+1 用来满足last的限制 保证后面仍然可以使用L+1这种跳法的策略
注意:
石头要排序 输入不是有序的
如果用i表示当前位置前面的石头的序号 那么每次跳之后都要维护i 要不然可能会踩在i石头上
代码:
#include<cstdio> #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<cassert> #include<vector> #include<set> #include<map> #include<queue> using namespace std; #define N 200010 int x[N]; int T, t, n, m, L, ans; int main() { int i, now, last, time; scanf("%d", &T); for (t = 1; t <= T; t++) { scanf("%d%d%d", &n, &m, &L); for (i = 1; i <= n; i++) scanf("%d", &x[i]); n++; sort(x + 1, x + n); x[n] = m; now = ans = 0; last = L + 1; for (i = 1; now < m;) { if (now + L >= x[i]) { ans++; for (; i <= n; i++) { if (now + L < x[i]) break; } i--; last = x[i] - now; now = x[i]; i++; } else { time = (x[i] - now) / (L + 1) - 1; ans += time * 2; now += time * (L + 1); ans++; last = L + 1 - last; now += last; for (; i <= n; i++) { if (x[i] > now) break; } } } printf("Case #%d: %d\n", t, ans); } return 0; }
原文地址:http://blog.csdn.net/houserabbit/article/details/39545891