2328: [HNOI2011]赛车游戏 - BZOJ
先把一定要减的费用先减掉,就是b*s*len(上坡路),下坡路就设一个初速度,使耗油为0,如果没油了,就无法到达
然后考虑加速
对于长度为len的路,增加v的速度需要len*a*v的油,与len成正比
然后又因为原来的速度越小,增加等量v的增益越高,所以每次都从最小的速度开始加(不超过第二小),还有不要超过vmax
1 const 2 maxn=10010; 3 var 4 t,n:longint; 5 a,b,vmax,f:double; 6 len,s,v:array[0..maxn]of double; 7 8 procedure init; 9 var 10 i:longint; 11 x,y:double; 12 begin 13 read(a,b,vmax,f,n); 14 for i:=1 to n do 15 begin 16 read(x,y); 17 len[i]:=sqrt(sqr(x)+sqr(y))/1000; 18 s[i]:=y/x; 19 if s[i]>0 then f:=f-len[i]*b*s[i]; 20 if s[i]<0 then v[i]:=-b*s[i]/a 21 else v[i]:=0; 22 end; 23 end; 24 25 procedure swap(var x,y:double); 26 var 27 t:double; 28 begin 29 t:=x;x:=y;y:=t; 30 end; 31 32 procedure sort(l,r:longint); 33 var 34 i,j:longint; 35 y:double; 36 begin 37 i:=l; 38 j:=r; 39 y:=v[(l+r)>>1]; 40 repeat 41 while v[i]<y do 42 inc(i); 43 while v[j]>y do 44 dec(j); 45 if i<=j then 46 begin 47 swap(s[i],s[j]); 48 swap(v[i],v[j]); 49 swap(len[i],len[j]); 50 inc(i); 51 dec(j); 52 end; 53 until i>j; 54 if i<r then sort(i,r); 55 if j>l then sort(l,j); 56 end; 57 58 procedure work; 59 var 60 i,j:longint; 61 sum:double; 62 begin 63 sort(1,n); 64 for i:=1 to n do 65 if v[i]>vmax then v[i]:=vmax; 66 v[n+1]:=vmax; 67 sum:=0; 68 for i:=1 to n do 69 begin 70 sum:=sum+len[i]; 71 if v[i]<>v[i+1] then 72 begin 73 if f>=(v[i+1]-v[i])*sum*a then 74 begin 75 f:=f-(v[i+1]-v[i])*sum*a; 76 v[i]:=v[i+1]; 77 end 78 else 79 begin 80 v[i]:=v[i]+f/(sum*a); 81 break; 82 end; 83 end; 84 end; 85 for j:=i-1 downto 1 do 86 v[j]:=v[j+1]; 87 if v[1]=0 then 88 begin 89 writeln('IMPOSSIBLE'); 90 exit; 91 end; 92 sum:=0; 93 for i:=1 to n do 94 sum:=sum+len[i]/v[i]; 95 writeln(sum:0:5); 96 end; 97 98 begin 99 read(t); 100 while t>0 do 101 begin 102 init; 103 if f<0 then writeln('IMPOSSIBLE') 104 else work; 105 dec(t); 106 end; 107 end.