过河(NOIP2006)

deadrain 发表于 2007-08-14 21:38:01

因为桥的最大长度L=10^9,而石头数很少,可以把石头的位置离散开来。青蛙的最大跳跃距离是9和10,超过90的位置都可以到达,所以如果两颗石头的距离超过了90,就可以缩短到90。这样数据已经缩小到DP所能承受的范围了。
然后就是简单的DP。用数组f[i]表示到i位置最少要踩到的石头数,则f[i]=min(f[i-t]...f[i-s]),如果i位置上有石头,则加1。初始时如果i位置上有石头,f[i]=1,否则f[i]=maxint。最后因为青蛙可以跳过桥的终点(L),所以要统计L...L+t-1中最小的值,即为解。
另外,如果s=t,那么可以直接统计,如果某石头的位置是其倍数,肯定会被踩到,累计后可直接输出。

CODE:
-----------------------------------------------------
program p1002;
var
 l:longint;
 stone:array[0..101] of longint;
 f:array[-10..9010] of longint;
 s,t,n,i,j,sum,swap:longint;

function min(a,b:longint):longint;
begin
 if a<b then min:=a else min:=b;
end;

begin
 readln(l);
 readln(s,t,n);
 for i:=1 to n do read(stone[i]);

 if s=t then
 begin
  sum:=0;
  for i:=1 to n do
   if stone[i] mod s=0 then inc(sum);
  writeln(sum);
  halt;
 end;

 for i:=1 to n-1 do
  for j:=i+1 to n do
   if stone[i]>stone[j] then
   begin
    swap:=stone[i];stone[i]:=stone[j];stone[j]:=swap;
   end;

 stone[0]:=0;stone[n+1]:=l;
 for i:=1 to n+1 do
  if stone[i]-stone[i-1]>90 then
  begin
   sum:=stone[i]-stone[i-1]-90;
   for j:=i to n+1 do
    dec(stone[j],sum);
   stone[i]:=stone[i-1]+90;
  end;
 l:=stone[n+1];

 for i:=-t to l+t-1 do f[i]:=maxint;
 for i:=1 to n do
  f[stone[i]]:=1;

 f[0]:=0;
 for i:=1 to l+t-1 do
 begin
  sum:=maxint;
  for j:=i-t to i-s do
   sum:=min(sum,f[j]);
  if f[i]=1 then f[i]:=sum+1 else f[i]:=sum;
 end;

 sum:=f[l];
 for i:=l+1 to l+t-1 do
  if f[i]<sum then sum:=f[i];
 writeln(sum);
end.

关键词(Tag): noip vijos


收藏: QQ书签 del.icio.us 订阅: Google 抓虾

最新评论


  • fuck
    2008-11-10 16:25:16 匿名 59.61.*.*

发表评论

* 昵称

已经注册过? 请登录

新用户请先注册 以便能显示头像及追踪评论回复

Email
网址
* 评论
表情
 
 

分类小组论坛
杂谈, 娱乐、八卦, 文学、艺术, 体育, 旅游、同城, 象牙塔, 情感, 时尚、生活, 星座, 科技

请注意遵守中华人民共和国法律法规, 如威胁到本站生存, 将依法向有关部门报告, 同时本站的相关记录可能成为对您不利的证据.

相关法律法规
全国人大常委会关于维护互联网安全的决定
中华人民共和国计算机信息系统安全保护条例
中华人民共和国计算机信息网络国际联网管理暂行规定
计算机信息网络国际联网安全保护管理办法
计算机信息系统国际联网保密管理规定