zoukankan      html  css  js  c++  java
  • vj p1002题解

    具体内容参看原题

    停牛们说这是noip最难的一道DP,不知是不是真的,个人感觉没有多进程DP难。

    我是这样做的:(当然,在大牛的帮助下)

    DP方程很好想:

    f[i]=f[i-k] or f[i],(k=s..t);

    但是问题在于巨大的数据范围,对于30%的数据,L <= 10000;对于全部的数据,L <= 10^9。

    所以这样做绝对挂掉。

    仔细看,会发现石子数M的范围很小,1 <= M <= 100,如果以最大的数据来看,平均10^7的距离中有一颗石子,也就是说,在巨长的桥中间很散的分布着石子,而有这大段大段的空位置,甚至会出现在一段距离内,无论如何跳都踩不到石子的情况。

    再发挥下我们的想象:科幻电影中不是有很多关于宇宙旅行的东西么?怎样进行超光速飞行呢?那么,就是进行虫洞跳跃!想到这,方法就出来了!那就是虫洞跳跃!事实上,就是DP状态压缩!

    因为步长为s..t,而1 <= S <= T <= 10,

    先讨论特殊情况:如果s=t,那么就不用DP,直接搜索即可。

    如果S<T,

    假设s=9,t=10,那么在90步后的任意一步,都可以用s和t的组合来达到:

    如:要到91步,则9*s+t;同理,92:=8*s+2*t……

    也就是说,如果s=t-1,那么必然能通过组合表示t*(t-1)后的数字。

    推广开,就是当一个数k>t*(t-1)时,那么k必然可以用t和一个比t小而比s大的数表示。

    证毕!

    证明这个有什么用呢?当然有用了,这就是进行“空间跳跃”的基础!

    如果两个石子之间的空格超过了t*(t-1)那么就直接把这两段之间连个虫洞,中间的距离省掉。

    这样压缩后的结果就是将10^9的路程压缩成了最大100*90的路程,实现了一个质的飞跃!

    代码如下:

     1 var count,s,j,i,t,m,l,ls:longint;a,b,c:array[0..200]of longint;
     2     f:array[0..100000]of longint;
     3     v:array[0..100000]of boolean;
     4 procedure qsort(l,r:longint);
     5   var i,j,t,x:longint;
     6   begin
     7     i:=l;j:=r;
     8     x:=a[(i+j)div 2];
     9     repeat
    10       while a[i]<do inc(i);
    11       while a[j]>do dec(j);
    12       if i<=then
    13         begin
    14           t:=a[i];a[i]:=a[j];a[j]:=t;
    15           inc(i);dec(j);
    16         end;
    17     until i>j;
    18     if j>then qsort(l,j);
    19     if i<then qsort(i,r);
    20   end;
    21 begin
    22   
    23   readln(l);
    24   readln(s,t,m);
    25   for i:=1 to m do read(a[i]);
    26   qsort(1,m);
    27   while a[m]>do dec(m);
    28   if s=then
    29     begin
    30       count:=0;
    31       for i:=1 to m do
    32         begin
    33           if a[i] mod s=0 then inc(count);
    34         end;
    35     end
    36   else
    37     begin
    38       a[0]:=0;
    39       b[0]:=0;
    40       ls:=t*(t-1);
    41       fillchar(v,sizeof(v),0);
    42       for i:=1 to m do
    43         begin
    44           if a[i]-a[i-1]>ls then
    45             begin
    46               b[i]:=b[i-1]+ls;
    47             end
    48           else b[i]:=b[i-1]+a[i]-a[i-1];
    49           v[b[i]]:=true;
    50         end;
    51       if l-b[m]>ls then l:=b[m]+ls;
    52       fillchar(f,sizeof(f),100);
    53       f[0]:=0;
    54       for i:=to l+do
    55         for j:=downto s do if i-j>=0 then
    56           begin
    57             if f[i-j]+ord(v[i-j])<f[i] then f[i]:=f[i-j]+ord(v[i-j]);
    58           end;
    59       count:=maxlongint;
    60       for i:=to l+do
    61         begin
    62           if f[i]<count then
    63             count:=f[i];
    64         end;
    65     end;
    66   writeln(count);
    67   
    68 end.
  • 相关阅读:
    C#数据结构一:基础知识
    使用工厂方法模式实现多数据库WinForm手机号码查询器(附源码)
    我的个人年度总结
    CutePsWheel javascript libary:控制输入文本框为可使用滚轮控制的js库
    CSS制作无图片圆角矩形
    将SqlServer数据库转换Sqlite的工具
    原创电子书:C#难点逐个击破
    (译)在非IE浏览器中实现“灰阶化”
    extjs 记录一下
    Ext.Window相关
  • 原文地址:https://www.cnblogs.com/waterfalleagle/p/1591852.html
Copyright © 2011-2022 走看看