hdu 5037 Frog

这题如果用普通的暴力不加优化分分钟超时,因为是10^9,最坏情况会超过10^7计算量,

超时代码:

//K - Frog
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define MAXN 200000
typedef long long LL;

LL R[MAXN];//存放初始化即有的石头的位置

int main()
{
    int i,j;
    LL N,M,L;
    int kase,casenum;
    int ans;
    LL pre;
    LL pos;

    scanf("%d",&casenum);
    kase=0;
    while(casenum--)
    {
        scanf("%lld%lld%lld",&N,&M,&L);
        memset(R,0,sizeof(R));
        for(i=1;i<=N;i++)
            scanf("%lld",&R[i]);
        sort(R+1,R+1+N);
        ans=pos=pre=0;
        i=1;
        while(pos<M)
        {
            for(;i<=N;i++)
                if(R[i]<=pos+L&&R[i+1]>pos+L)
                    break;
            if(i==N+1)//如果i>N有可能是所有石头都在跳跃范围内
            {
                pos=R[i-1];
                ans++;
                if(pos+L>=M)
                {
                    ans++;
                    break;
                }
                i++;//因为在这种情况下下一轮跳跃就应该是人工加石头了
            }
            else
            {
                if(i>N+1)//初始化的石头已经跳完了
                {
                    while(pos<M)
                    {
                        ans++;
                        pos++;
                        if(pos+L>=M)
                        {
                            pos=M;
                            ans++;
                            break;
                        }
                    }
                }
                else//还剩余了初始化的石头
                {
                    if(i==pre)//接下来他一块石头也够不着
                    {
                        i++;
                        for(j=R[i];j>=1;j--)
                        {
                            if(pos+L+j<R[i]&&pos+L+j+1>=R[i])
                            {
                                pos=R[i];
                                i++;
                                ans+=j;
                                break;
                            }
                        }
                    }
                    else//有石头可以落脚
                    {
                        pos=R[i];
                        i++;
                        a//K - Frog
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define MAXN 200000
typedef long long LL;

LL R[MAXN];//存放初始化即有的石头的位置

int main()
{
    int i,j;
    LL N,M,L;
    int kase,casenum;
    int ans;
    LL pre;
    LL pos;

    scanf("%d",&casenum);
    kase=0;
    while(casenum--)
    {
        scanf("%lld%lld%lld",&N,&M,&L);
        memset(R,0,sizeof(R));
        for(i=1;i<=N;i++)
            scanf("%lld",&R[i]);
        sort(R+1,R+1+N);
        ans=pos=pre=0;
        i=1;
        while(pos<M)
        {
            for(;i<=N;i++)
                if(R[i]<=pos+L&&R[i+1]>pos+L)
                    break;
            if(i==N+1)//如果i>N有可能是所有石头都在跳跃范围内
            {
                pos=R[i-1];
                ans++;
                if(pos+L>=M)
                {
                    ans++;
                    break;
                }
                i++;//因为在这种情况下下一轮跳跃就应该是人工加石头了
            }
            else
            {
                if(i>N+1)//初始化的石头已经跳完了
                {
                    while(pos<M)
                    {
                        ans++;
                        pos++;
                        if(pos+L>=M)
                        {
                            pos=M;
                            ans++;
                            break;
                        }
                    }
                }
                else//还剩余了初始化的石头
                {
                    if(i==pre)//接下来他一块石头也够不着
                    {
                        i++;
                        for(j=R[i];j>=1;j--)
                        {
                            if(pos+L+j<R[i]&&pos+L+j+1>=R[i])
                            {
                                pos=R[i];
                                i++;
                                ans+=j;
                                break;
                            }
                        }
                    }
                    else//有石头可以落脚
                    {
                        pos=R[i];
                        i++;
                        ans++;
                    }
                }
            }
        }
        printf("Case #%d: %d\n",++kase,ans);
    }
    return 0;
}
ns++;
                    }
                }
            }
        }
        printf("Case #%d: %d\n",++kase,ans);
    }
    return 0;
}

这题还是蛮难的,网上普遍流行两种做法。

(1)参考博客:

https://www.cnblogs.com/yuiffy/p/3984846.html

https://blog.csdn.net/weilehuozhe/article/details/48300165

https://www.cnblogs.com/yuiffy/p/3984846.html

这种方法其实是算一种模拟过程,然而并没有看懂代码。。。。

(2)我用的是第二种方法,参考博客:

https://blog.csdn.net/u014569598/article/details/39471913#commentsedit

https://blog.csdn.net/Irving0323/article/details/81781026

确实有点难理解,

http://my.csdn.net/my/album/detail/1786547

其实就拿0, 5, 8,其中L=3这组数据开涮,可以发现第一次默认是跳到了第一块石头上(先不管到底有没有通过sum+x>=L+1来判断是否再加一个1),意思是每次跳跃都默认跳到下一块石头上,而不管中间的距离是多少,也不管在哪里加石头,至于中间调不到的距离就用数学计算强制给他加上

所以说这是一种非模拟,纯计算的手段,但是分析起来好像没有那么复杂。

这里我有几个问题:

(1)

我的理解是,当sum的初值设为L时其实就已经避免了这种情况,以我上述的数据为例,当跳到5的时候,本来模拟过程应该是两步的,因为余数之和还没有>+L+1,但是在这一步程序走出来是3,所以是强制加一,所以这种问题可以避免。

但这样就又牵扯出来一个问题:但是如果最后一步的时候余数之和又大于L+1了答案就多了一?

其实是不会的,用我上述那个例子试出来是刚刚好。。。。(原因不详)

这种题一般要排序,题目很坑的。

还有,将起点和终点都加入R数组里面,是一个良好的习惯,就不用特意判断终点了。

核心代码:

代码:

//K - Frog
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define MAXN 200010
typedef long long LL;

int R[MAXN];//存放石头的初始位置

int main()
{
    int i;
    int N,M,L;
    int casenum,kase;
    int ans;
    int sum;//记录前几次的余数的和
    int x,y;

    scanf("%d",&casenum);
    kase=0;
    while(casenum--)
    {
        scanf("%d%d%d",&N,&M,&L);
        memset(R,0,sizeof(R));
        for(i=1;i<=N;i++)
            scanf("%d",&R[i]);
        R[0]=0;
        R[N+1]=M;
        sort(R,R+N+1);
        sum=L;
        ans=0;
        for(i=1;i<=N+1;i++)
        {
            x=(R[i]-R[i-1])%(L+1);
            y=(R[i]-R[i-1])/(L+1);
            if(sum+x>=L+1)
            {
                ans++;
                sum=x;
            }
            else
                sum+=x;
            ans+=2*y;
        }
        printf("Case #%d: %d\n",++kase,ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/fx714848657/article/details/81839611