sωēeτ¨fαrm » 日志 » 过河(NOIP2006)
过河(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.
- » NOIP结束了
- » 镇江一游(2)
- » 镇江一游(1)
- » zoj 1002 Fire Net
- » 告别之战




