• 【ZJOI2017 Round1练习&BZOJ5350】D5T1 masodik(DP,斜率优化)


    题意:你要从(0,0)点走到(n,m), 每次只能往 x 轴或者 y 轴正方向移动一个单位距离。
    从(i,j)移动到(i,j+1)的代价为 ri,从(i,j)移动到(i+1,j)的代价为 cj。

    求最小代价。

    对于 20%的数据, n, m<=5000。
    对于 100%的数据, n, m<=10^5,0<ri,ci<=10^8。

    思路:杜教原题

    建出rc的下凸壳,每次走斜率大的那个。
    证明?

    • P q
    • | |
    • a--|-----|---
    • b--|-----|---
    • ra(q-p)+cp(a-b)<=rb(q-p)+cq(a-b)
    • (ra-rb)(q-p)<=(cq-cp)(a-b)
    • (ra-rb)/(a-b)<=(cq-cp)/(q-p)<=.......(more columns and
    rows.
    斜率?
    每次走过路径斜率递增--->下凸
    如何证明在下凸壳上?

    下凸壳显然 假设当前是第x1行第y1列,下一个行和列是x2和y2,那么考虑是先沿行走还是先沿列走

    先沿行走:r[x1]*(y2-y1)+c[y2]*(x2-x1)

    先沿列走:r[x2]*(y2-y1)+c[y1]*(x2-x1)

    r[x1]*(y2-y1)+c[y2]*(x2-x1)<r[x2]*(y2-y1)+c[y1]*(x2-x1)

    (r[x2]-r[x1])/(x2-x1)>(c[y2]-c[y1])/(y2-y1)

    于是先沿斜率大的走

     1 var x,y:array[0..200000,1..2]of longint;
     2     q1,q2:array[0..200000]of longint;
     3     r,c:array[0..200000]of int64;
     4     n,m,i,j,l1,l2:longint;
     5     k1,k2:double;
     6     ans:int64;
     7 
     8 function slope(i,j,k:longint):double;
     9 begin
    10  exit((y[i,k]-y[j,k])/(x[i,k]-x[j,k]));
    11 end;
    12 
    13 function clac(x1,y1,x2,y2,k:longint):int64;
    14 begin
    15  if k=1 then exit(r[x1]*(y2-y1)+c[y2]*(x2-x1))
    16         else exit(c[y1]*(x2-x1)+r[x2]*(y2-y1));
    17 end;
    18 
    19 begin
    20  assign(input,'masodik.in'); reset(input);
    21  assign(output,'masodik.out'); rewrite(output);
    22  readln(n,m);
    23  for i:=0 to n do
    24  begin
    25   read(y[i,1]); x[i,1]:=i; r[i]:=y[i,1];
    26  end;
    27  for i:=0 to m do
    28  begin
    29   read(y[i,2]); x[i,2]:=i; c[i]:=y[i,2];
    30  end;
    31  for i:=0 to n do
    32  begin
    33   while (l1>1)and(slope(i,q1[l1],1)<=slope(q1[l1-1],q1[l1],1)) do dec(l1);
    34   inc(l1); q1[l1]:=i;
    35  end;
    36  for i:=0 to m do
    37  begin
    38   while (l2>1)and(slope(i,q2[l2],2)<=slope(q2[l2-1],q2[l2],2)) do dec(l2);
    39   inc(l2); q2[l2]:=i;
    40  end;
    41  i:=1; j:=1;
    42  while (i<l1)and(j<l2) do
    43  begin
    44   k1:=slope(q1[i],q1[i+1],1);
    45   k2:=slope(q2[j],q2[j+1],2);
    46   if k1>k2 then
    47   begin
    48    ans:=ans+clac(q1[i],q2[j],q1[i],q2[j+1],1);
    49    inc(j);
    50   end
    51   else
    52   begin
    53    ans:=ans+clac(q1[i],q2[j],q1[i+1],q2[j],2);
    54    inc(i);
    55   end;
    56  end;
    57  while i<l1 do
    58  begin
    59   ans:=ans+clac(q1[i],q2[l2],q1[i+1],q2[l2],1);
    60   inc(i);
    61  end;
    62  while j<l2 do
    63  begin
    64   ans:=ans+clac(q1[l1],q2[j],q1[l1],q2[j+1],2);
    65   inc(j);
    66  end;
    67  writeln(ans);
    68 
    69 
    70  close(input);
    71  close(output);
    72 end.
  • 相关阅读:
    Web 前端开发中一些兼容性问题及其解决办法 (持续更)
    沈逸的IT专栏---shenyisyn
    程序员该做的事
    职场需要切忌的几点——《程序员,你伤不起》
    百度天气API接口
    C#简单音乐播放器ListBox歌单列表
    CentOS7 安装java(jre 1.8)
    CentOS7 系统安装与设置
    这个可以有,记录下
    在centos 7中让网卡自启动
  • 原文地址:https://www.cnblogs.com/myx12345/p/6513850.html
Copyright © 2020-2023  润新知