zoukankan      html  css  js  c++  java
  • 分层dp:天堂(heaven)

    题目描述
    每一个要上天堂的人都要经历一番考验,当然包括小X,小X开始了他进入天堂的奇异之旅。地狱有18层,天堂竟然和地狱一样,也有很多很多层,天堂共有N层。从下到上依次是第1,2,3,…,N层,天堂的每一层都是一个延伸无限远的地板,在地板上人可以任意走动,层与层之间是平行关系,每一层的地板都是由人不能穿过的物质构成,幸好每一层地板上有且仅有1个人可以通过的洞口。
    我们可以把小X和洞口,还有下面提到的气球店都看成点,坐标是二维的。小X开始在第
    3
    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

    可以看出,每一层与其它层是互不影响的。
    对于第x层,共有number[x]个气球店,气体浮力为air[x],即需领m-air[x]个气球
    f[i,j]表示在第i个气球点领取第j个气球
    f[i,j]:=min(f[k,j-1]+dist[i,j]) {i<>k}
    f[i,1]:=起点到每一个气球店的距离
    第x层最小的移动距离为min{f[i,m-air[x]]+终点到i的距离}

    and 不能再把数据范围看错了

    code:
    var n,m,q:longint;
    pole:array[1..200]of record
    x,y:longint;
    end;
    air:array[1..200]of longint;
    number:array[1..200]of longint;
    position:array[1..200,1..60]of record
    x,y:longint;
    end;
    f:array[1..1010,1..1000]of double;
    dist1,dist2:array[1..100]of double;
    dist:array[1..100,1..100]of double;
    ii,i,j,k:longint;
    sx,sy,fx,fy:longint;
    x,y,z:longint;
    min,ans:double;
    temp:double;
    begin 
    readln(n,m,q);
    for i:=2 to n do
    read(pole[i].x,pole[i].y);
    for i:=1 to n-1 do
    read(air[i]);
    fillchar(position,sizeof(position),0);
    fillchar(number,sizeof(number),0);
    for i:=1 to q do
    begin readln(x,y,z);
    inc(number[z]);
    position[z,number[z]].x:=x;
    position[z,number[z]].y:=y;
    end;
    ans:=0;
    sx:=pole[1].x;
    sy:=pole[1].y;
    for ii:=1 to n-1 do
    begin if air[ii]<m
    then begin fillchar(dist1,sizeof(dist1),0);
    fillchar(dist2,sizeof(dist2),0);
    fillchar(dist,sizeof(dist),0);
    for i:=1 to number[ii] do
    dist1[i]:=sqrt(sqr(position[ii,i].x-sx)+
    sqr(position[ii,i].y-sy));
    for i:=1 to number[ii] do
    for j:=1 to number[ii] do
    dist[i,j]:=sqrt(sqr(position[ii,i].x-position[ii,j].x)+
    sqr(position[ii,i].y-position[ii,j].y));
    for i:=1 to number[ii] do
    for j:=1 to m-air[ii] do
    f[i,j]:=maxint*5000;
    for i:=1 to number[ii] do
    f[i,1]:=dist1[i];
    fx:=pole[ii+1].x;
    fy:=pole[ii+1].y;
    for i:=1 to number[ii] do
    dist2[i]:=sqrt(sqr(position[ii,i].x-fx)+
    sqr(position[ii,i].y-fy));
    for j:=2 to m-air[ii] do
    for i:=1 to number[ii] do
    for k:=1 to number[ii] do
    if (f[i,j]>f[k,j-1]+dist[i,k])and(i<>k)
    then f[i,j]:=f[k,j-1]+dist[i,k];
    min:=maxlongint;
    for i:=1 to number[ii] do
    if min>f[i,m-air[ii]]+dist2[i]
    then min:=f[i,m-air[ii]]+dist2[i];
    ans:=ans+min;
    sx:=pole[ii+1].x;
    sy:=pole[ii+1].y;
    end
    else begin fx:=pole[ii+1].x;
    fy:=pole[ii+1].y;
    ans:=ans+sqrt(sqr(sx-fx)+sqr(sy-fy));
    sx:=pole[ii+1].x;
    sy:=pole[ii+1].y;
    end;
    end;
    writeln(ans:0:2);

    end.
  • 相关阅读:
    <玩转Django2.0>读书笔记:模板和模型
    <玩转Django2.0>读书笔记:URL规则和视图
    学习随笔:Vue.js与Django交互以及Ajax和axios
    <算法图解>读书笔记:第4章 快速排序
    <算法图解>读书笔记:第3章 递归
    <算法图解>读书笔记:第2章 选择排序
    <算法图解>读书笔记:第1章 算法简介
    PostgreSQL自学笔记:与python交互
    AS3 setInterval
    AS3 事件流
  • 原文地址:https://www.cnblogs.com/spiderKK/p/4893652.html
Copyright © 2011-2022 走看看