• NOIP 2005 提高组 过河


    题目摘自RQNOJ:http://www.rqnoj.cn/Problem_17.html

     

    题目描述

      在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点: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个石子在数轴上的位置(数据保证桥的起点和终点处没有石子)。所有相邻的整数之间用一个空格隔开。

    输出格式

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

    样例输入

    10
    2 3 5
    2 3 5 6 7

    样例输出

    2

     

    题解:

      应WK大神的要求,还是把这道题的题解给写了。

     

      首先第一思路肯定是个背包,用f[i]表示走到i这个格子最少需踩多少石子,状态转移方程为1、i有石子:f[i]=min(f[i-step]+1)(s<=step<=t) 2、i无石子:f[i]=min(f[i-step])(s<=step<=t)。但是L<=10^9,就赤裸裸地TLE了,所以必须优化。

     

      观察到一个很有用的条件,1<=S<=T<=10,也就是说每次最多跳10的距离,另外M<=100,石子数非常少,也就是说有很长的没有任何意义的区间,那么减少转移次数就从这里入手。

     

      考虑1<=S<=T<=10,当S=T时,这个只有一种跳法,特殊处理。当S!=T时,我们考虑从起点出发,有哪些长度是走不到的,那些长度是能走到的,可以证明,大于等于T*(T-1)的长度时,一定是可以走到的(不要问我为什么,这是常识),由于T<=10,我们可以考虑为只要距离大于100的一定可以从起点到达,距离100以内的则可以用一个简单DP提前预处理出来。同理,一旦两个点的距离大于了100,那么它们一定可以由其中的一个到达另一个。也就是说,任意两个距离大于一百的点都可以把他们的距离缩小为100,而这不会对答案有任何的影响。于是我们只需要把所有石子的坐标排个序,距离大于100的缩为100,这样最多的长度也只有100*100左右,然后,裸的DP即可。

     

      最后还是 sro sro sro sro sro WK大神牛 orz orz orz orz orz

      这题是很早以前写的了,代码非常丑,也不想重写,就这样吧。

    View Code
     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 
     5 using namespace std;
     6 
     7 const int maxn=200000;
     8 
     9 int l,s,t,m,a,b,dp[maxn],sb[101],ans,now;
    10 
    11 bool stone[maxn];
    12 
    13 int qsort(int a,int b)
    14 {
    15     int c,d,e,f;
    16     c=a;
    17     d=b;
    18     e=sb[(a+b)>>1];
    19     do
    20     {
    21         while (sb[c]<e)
    22             c++;
    23         while (e<sb[d])
    24             d--;
    25         if (c<=d)
    26         {
    27             f=sb[c];
    28             sb[c]=sb[d];
    29             sb[d]=f;
    30             c++;
    31             d--;
    32         }
    33     }while (c<=d);
    34     if (c<b) qsort(c,b);
    35     if (a<d) qsort(a,d);
    36     return(0);
    37 }
    38 
    39 int main()
    40 {
    41     freopen("river.in","r",stdin);
    42     freopen("river.out","w",stdout);
    43 
    44     scanf("%d",&l);
    45     scanf("%d%d%d",&s,&t,&m);
    46     if (s==t)
    47     {
    48         for (a=1;a<=m;a++)
    49         {
    50             scanf("%d",&b);
    51             if (b % s==0) ans++;
    52         }
    53         printf("%d\n",ans);
    54         return(0);
    55     }
    56     for (a=1;a<=m;a++)
    57         scanf("%d",&sb[a]);
    58     qsort(1,m);
    59     memset(stone,false,sizeof(stone));
    60     sb[0]=0;
    61     for (a=1;a<=m;a++)
    62     {
    63         if (sb[a]-sb[a-1]>=s*t*2) 
    64         {
    65             now=sb[a]-sb[a-1]-2*s*t;
    66             for (b=a;b<=m;b++)
    67                 sb[b]=sb[b]-now;
    68         }
    69         stone[sb[a]]=true;
    70     }
    71     memset(dp,0x3f,sizeof(dp));
    72     dp[0]=0;
    73     l=sb[m]+t+1;
    74     for (b=s;b<=l;b++)
    75         for (a=s;a<=t;a++)
    76             if (b-a>=0)
    77             {
    78                 if (stone[b]==true) now=1+dp[b-a];
    79                 else now=dp[b-a];
    80                 if (now<dp[b]) 
    81                 {
    82                     dp[b]=now;
    83                 }
    84             }
    85     printf("%d\n",dp[l]);
    86     
    87     return 0;
    88 }

      

  • 相关阅读:
    (转)一次棘手的rootvg更换硬盘处理过程
    mysql:服务器错误代码
    (转)运行跟踪格式化程序
    (转)InnoDB存储引擎MVCC实现原理
    (转)漫谈JVM
    (转)mysql、innodb和加锁分析
    (转)DB2和 Oracle的并发控制(锁)比较
    (转)Mysql主从复制搭建及详解
    BigDecimal 、BigInteger
    Date、DateFormat、SimpleDateFormat、Calendar
  • 原文地址:https://www.cnblogs.com/zhonghaoxi/p/2476940.html
Copyright © 2020-2023  润新知