XYLX 10.19 天堂(HEAVEN)
題目描述
每一個要上天堂的人都要經歷一番考驗,當然包括小X,小X開始了他進入天堂的奇異之旅。地獄有18層,天堂竟然和地獄一樣,也有很多很多層,天堂共有N層。從下到上依次是第1,2,3,…,N層,天堂的每一層都是一個延伸無限遠的地板,在地板上人可以任意走動,層與層之間是平行關係,每一層的地板都是由人不能穿過的物質構成,幸好每一層地板上有且僅有1個人可以通過的洞口。
我們可以把小X和洞口,還有下面提到的氣球店都看成點,座標是二維的。小X開始在第1層的(0,0).
小X的重量爲M,第i層與第i+1層之間的特殊氣體能浮起的重量爲Wi ,每一層的地面上散落了若干個氣球店,多個氣球店可以在同一點,每個氣球可以浮起的重量是1,去一個氣球店一次只能領取一個氣球,不能連續在一個氣球店領取氣球,當然你可以在兩個氣球店之間來回跑,每個氣球店供應的氣球都是無限多的。第i層的氣球只能在第i層進入第i+1層時使用,當小X在第i層,只有站到了第i+1層洞口的位置(在其它位置不會浮起),並且自身的重量小於等於氣球和特殊氣體浮起重量的總和,纔可以進入第i+1層。小X想知道他要到達第N層走過的長度最少是多少?題目保證有解。
輸入輸出
輸入文件
第1行: 三個正整數N,M,Q(Q表示氣球店)
第2行: 共2*(N-1)個整數,每兩個數描述1個洞口座標,第i對xi,yi表示第i+1層的洞口位置(xi,yi)。
第3行: 共N-1個整數,第i個數爲Wi。
往後Q行,每行三個整數x,y,z , 表示第Z層有一個氣球店,座標爲(x,y)
輸出文件
1個實數L,保留兩位小數,表示小X最少要走的長度。
樣例
樣例輸入
3 10 4
0 0 1 2
9 0
0 1 1
2 3 1
0 1 2
1 1 2
樣例輸出
13.00
註釋
【樣例解釋】
在第一層從(0,0)出發到(0,1)取得1個氣球並返回(0,0)即可到達第二層。長度:2.00
在第二層,從(0,0)到(0,1)領取氣球,再到(1,1)領取氣球,兩個點來回跑,第5次到達(1,1)時恰好氣球數達到10,走到(1,2)即可到達第3層終點。長度:11.00
總長度:13.00
【數據範圍】
2<=N<=100
每層的氣球店數目不超過50。
0<=M<=100, 0<=Wi<=100
座標-3000<=x,y<=3000
分析
從網上看題解後自己的總結
首先要到最高層,每層都是互不影響的,所以分層動歸,當每層都是最小的時候肯定所有也是最小,因此我們對該題分層動歸,當特殊氣球即可滿足需求時代價就爲從一點到另一點的距離;
方程
f[i,j]:=min(f[i,j],f[i-1,p]+從p氣球店到j氣球店的距離)(p<>j,p∈該層所有氣球店)
f[1,j]:=(從起點到j氣球店的距離)
代碼如下
program heaven;
type rec=record
x,y:longint;
end;
var i,j,k,p,n,m,q,w,x,y,z:longint;
ans,minn:double;
sum:array[1..100] of integer;
balloon:array[1..100,1..50] of rec;
need:array[1..100] of longint;
elevator:array[1..100] of rec;
f:array[0..100,1..100] of double;
function min(a,b:double):double;
begin
if a<b then exit(a);
exit(b);
end;
begin
readln(n,m,q);
for i:=1 to n-1 do
begin
read(elevator[i].x,elevator[i].y);
end;
for i:=1 to n-1 do
begin
read(w);
need[i]:=m-w;
end;
for i:=1 to q do
begin
readln(x,y,z);
inc(sum[z]);
balloon[z,sum[z]].x:=x;
balloon[z,sum[z]].y:=y;
end;
x:=0;
y:=0;
for i:=1 to n-1 do
begin
if need[i]<=0
then
begin
ans:=ans+sqrt(sqr(elevator[i].x-x)+sqr(elevator[i].y-y));
x:=elevator[i].x;
y:=elevator[i].y;
end
else
begin
for j:=1 to sum[i] do
f[1,j]:=sqrt(sqr(balloon[i,j].x-x)+sqr(balloon[i,j].y-y));
for k:=2 to need[i] do
begin
for j:=1 to sum[i] do
begin
f[k,j]:=maxlongint;
for p:=1 to sum[i] do
begin
if j<>p
then
f[k,j]:=min(f[k,j],f[k-1,p]+sqrt(sqr(balloon[i,j].x-balloon[i,p].x)+sqr(balloon[i,j].y-balloon[i,p].y)));
end;
end;
end;
minn:=maxlongint;
for j:=1 to sum[i] do
begin
minn:=min(minn,f[need[i],j]+sqrt(sqr(balloon[i,j].x-elevator[i].x)+sqr(balloon[i,j].y-elevator[i].y)));
end;
ans:=ans+minn;
x:=elevator[i].x;
y:=elevator[i].y;
end;
end;
write(ans:0:2);
end.
套用
仍然空洞的明日 是最接近黑的灰
無法成爲任何東西 是最接近黑的灰