HDU 5037 题解

来源:互联网 发布:c语言开发环境 编辑:程序博客网 时间:2024/06/06 07:49

转载请注明出处,http://blog.csdn.net/Bule_Zst/article/details/77884387


题目:http://acm.hdu.edu.cn/showproblem.php?pid=5037

Problem Description

Once upon a time, there is a little frog called Matt. One day, he came to a river.

The river could be considered as an axis.Matt is standing on the left bank now (at position 0). He wants to cross the river, reach the right bank (at position M). But Matt could only jump for at most L units, for example from 0 to L.

As the God of Nature, you must save this poor frog.There are N rocks lying in the river initially. The size of the rock is negligible. So it can be indicated by a point in the axis. Matt can jump to or from a rock as well as the bank.

You don’t want to make the things that easy. So you will put some new rocks into the river such that Matt could jump over the river in maximal steps.And you don’t care the number of rocks you add since you are the God.

Note that Matt is so clever that he always choose the optimal way after you put down all the rocks.

Input

The first line contains only one integer T, which indicates the number of test cases.

For each test case, the first line contains N, M, L (0<=N<=2105,1<=M<=109, 1<=L<=109).

And in the following N lines, each line contains one integer within (0, M) indicating the position of rock.

Output

For each test case, just output one line “Case #x: y”, where x is the case number (starting from 1) and y is the maximal number of steps Matt should jump.

Sample Input

21 10 552 10 336

Sample Output

Case #1: 2Case #2: 4

题目大意:

有一只萌萌哒小青蛙要过河,过河路线可以看成一个数轴,起点为0,终点为m。

小青蛙不会游泳,只能跳到数轴上一些有树桩的点直到跳过河,小青蛙一次能跳的最大距离是L。

小青蛙想用尽量少的步数过河,而你想让他跳尽量多的次数。

现在你可以向数轴上一些位置添加树桩,使青蛙顺利过河,并达到你的目的。青蛙是以最佳策略过河的。

— hdu5037 Frog — 贪心

方法:

首先将题目给的石头进行排序(坑点)(还需加上起始点与终点),之后遍历这些石头,维护变量last(上次跳跃的距离),基于x、y累加结果,具体逻辑流程看代码

算法核心讲解:

分了两种情况,last + x 大于等于 a + 1 与小于

首先明确一个结论,对于a、b、c三点,若b、c之间的距离为a+1,则一定可以让青蛙跳到c点的同时,让它这一步的步长等于a与b之间的距离(<= ability)。证明如下:

现已确定abc三点,且青蛙在b点无法跳跃到c点

那么,青蛙从b点起跳,下一个落脚点一定是d点(满足:d-a == ability+1),因为若存在d1落脚点(< d),则青蛙就可以直接从a点跳到d1而不经过b了。

接下来,从d起跳,下一个落脚点一定是e(满足:e-b == ability+1)

a、b、d、e、c

因为e-b == ability+1,所以c与e重合

a、b、d、e

d - a == e - b

所以e - d == b - a

证毕

现在来解释代码

首先计算出y,即两石头间(a、b)存在y个ability+1的距离,所以结果加上2*y,设跳完这y的距离之后的落脚点为k,那么根据之前的结论,跳到k的这一步的步长为最初跳到a点的步长(last)

此时,距离b点还剩下x的距离,如果x加上last小于等于ability,那么青蛙就肯定不会落脚k点,而是直接跳到b点,而如果大于ability,那么青蛙只能跳到k点再跳到b点,所以要再加一

代码:

// @Team    : nupt2017team12// @Author  : Zst#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <string>#include <vector>#include <cmath>#include <algorithm>#include <map>using namespace std;#define LL long long#define MOD 1000000007#define CLR(a,x) memset(a,x,sizeof(a))#define INF 0x3f3f3f3f#define pb push_back#define FOR(i,a,b) for( int i = ( a ); i <= ( b ); ++i )const int N = 2*1e5+7;int n, d, a;int stone[N];int main(){    // freopen( "F.txt", "r", stdin );    int w;    scanf( "%d", &w );    int cases = 1;    while( w-- ) {        scanf( "%d%d%d", &n, &d, &a );        FOR( i, 1, n ) {            scanf( "%d", stone+i );        }        stone[++n] = d;        stone[0] = 0;        sort( stone, stone+n+1 );        int last = a;        int ans = 0;        FOR( i, 1, n ) {            int x = ( stone[i] - stone[i-1] ) % ( a + 1 );            int y = ( stone[i] - stone[i-1] ) / ( a + 1 );            if( last + x >= a + 1 ) {                ans += 2 * y + 1;                last = x;            } else {                ans += 2 * y;                last = last + x;            }        }        printf( "Case #%d: %d\n",cases++,ans);    }    return 0;}
原创粉丝点击