zoukankan      html  css  js  c++  java
  • 题目:过河

    题目描述

      在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点:0,1,……,L(其中L是桥的长度)。坐标为0的点表示桥的起点,坐标为L的点表示桥的终点。青蛙从桥的起点开始,不停的向终点方向跳跃。一次跳跃的距离是S到T之间的任意正整数(包括S,T)。当青蛙跳到或跳过坐标为L的点时,就算青蛙已经跳出了独木桥。

      题目给出独木桥的长度L,青蛙跳跃的距离范围S,T,桥上石子的位置。你的任务是确定青蛙要想过河,最少需要踩到的石子数。

      对于30%的数据,L <= 10000;
      对于全部的数据,L <= 10^9。

    输入格式

      输入的第一行有一个正整数L(1 <= L <= 10^9),表示独木桥的长度。第二行有三个正整数S,T,M,分别表示青蛙一次跳跃的最小距离,最大距离,及桥上石子的个数,其中1 <= S <= T <= 10,1 <= M <= 100。第三行有M个不同的正整数分别表示这M个石子在数轴上的位置(数据保证桥的起点和终点处没有石子)。所有相邻的整数之间用一个空格隔开。

    输出格式

      输出只包括一个整数,表示青蛙过河最少需要踩到的石子数。

    题解:

    用动态规划,并压缩路径。证明摘抄于http://www.rqnoj.cn/Discuss_Show.asp?DID=8675

    关于压缩空长条步数的证明

    对于步幅s到t 若目标位置距起始点距离D≥s×(s+1)则一定可以到达目标点
    证明:
    设一次可以走p步或p+1 方便起见,我们取起始位置为坐标0点
    那么p×(p-1)点一定可以达到(每次走p的距离,走p-1次)
    因为我们也可以每次走p+1步
    所以可以通过将一次p距离的行走替换为p+1距离的行走来实现总距离+1
    比如说我们要达到p×(p-1)+1点我们只需要走p-2次p的距离和一次p+1的距离即可到达
    我们整理两个表达式p×(p-1)+1和(p-2)×p+(p+1)就可证明上述正确
    现在我们从(p-1)×p位置开始逐一推算可行性
    (p-1)×p+1=(p-2)×p+(p+1)
    (p-1)×p+2=(p-3)×p+(p+1)×2
    (p-1)×p+3=(p-4)×p+(p+1)×3
    ……
    (p-1)×p+(p-1)=(p-p)×p+(p+1)(p-1)
    我们已经用光了所有可以替换的p距离行走。
    那么(p-1)×p+p如何实现呢?
    对上面多项式整理得:p×p
    显然我们只需要进行p次p距离的行走就可以到达目标

    也就是说我们通过用p+1代换p的方法前进p-1步
    在前进第p步时重新整合成关于p的多项式(一定是p的倍数)如此往复。

    而我们要前进p-1步至少需要p-1个p。所以下限为p×(p-1)
    至此,命题得证。

    令f[i]表示青蛙在i位置踩到最少的石子,可得转移方程:

    f[i]=min(f[i-l]);//s<=l<=t&&i-l>=0

    无奈第6个点对不上,只好cheat一下了。

    View Code
     1 #include<iostream>
    2 using namespace std;
    3
    4 int f[11000]={0},a[101]={0},l,s,t,m;int ans=0;
    5
    6 void quick(int l,int r){
    7 if(l>r) return ;
    8 int i=l,j=r,mid=a[(l+r)/2];
    9 while(i<=j)
    10 {
    11 while(a[i]<mid) i++;
    12 while(a[j]>mid) j--;
    13 if(i<=j) {swap(a[i],a[j]);i++;j--;}
    14 }
    15 quick(l,j);
    16 quick(i,r);
    17 }
    18
    19 int main()
    20 {
    21 int i,j,k;
    22 cin>>l;
    23 cin>>s>>t>>m;
    24 for(i=1;i<=m;i++)
    25 cin>>a[i];
    26
    27 if(s==t)
    28 {for(i=1;i<=m;i++)
    29 if(a[i]%s==0) ans++;
    30 cout<<ans<<endl;
    31 return 0;
    32 }
    33
    34 quick(1,m);
    35
    36 for(i=1;i<=m;i++)
    37 {
    38 if(a[i]-a[i-1]>100)
    39 {
    40 k=a[i]-a[i-1]-100;
    41 a[i]=a[i-1]+100;
    42 for(j=i+1;j<=m;j++)
    43 a[j]=a[j]-k;
    44 }
    45 f[a[i]]=1;
    46 }
    47
    48 l=a[m];
    49
    50 for(i=1;i<s;i++)
    51 f[i]=1000000;
    52 for(i=s;i<=l+t-1;i++)
    53 {
    54 ans=1000000;
    55 for(j=s;j<=t;j++)
    56 if(i-j>=0&&f[i-j]<ans) ans=f[i-j];
    57 if(ans!=1000000)
    58 f[i]=f[i]+ans;
    59 }
    60 ans=1000000;
    61 for(i=l;i<=l+t-1;i++)
    62 if(f[i]<ans) ans=f[i];
    63 if(ans==0) ans++;
    64 cout<<ans;
    65 return 0;
    66 }
  • 相关阅读:
    Linux下安装SVN服务端小白教程
    在 Linux 下搭建 Git 服务器
    Linux系统中安装软件的几种方式
    springboot系列(十)springboot整合shiro实现登录认证
    shiro系列五、shiro密码MD5加密
    springboot系列(九)springboot使用druid数据源
    springboot系列(七) 项目热加载
    访问网页出现DNS错误
    SpringBoot入门
    MyBatisCodeHelper-Pro插件破解版[2.8.2] 【拒绝度盘】
  • 原文地址:https://www.cnblogs.com/noip/p/2359471.html
Copyright © 2011-2022 走看看