现在的位置: 首页 > 综合 > 正文

poj3666

2018年04月26日 ⁄ 综合 ⁄ 共 1344字 ⁄ 字号 评论关闭

【题意】

有n块高低不同的地面,每让一块高度改变1则需支付1的代价,问将地面高度变为不上升或不下降序列所需最小代价

【输入】

第一行一个n

接下来n行每行一个数字表示该块地面的高度

【输出】

一个数字,表示最小代价

离散高度后dp

用f[i][j]表示考虑钱i块地面,当前地面高度离散后为j的所需最小代价

f[i][j]=min(f[i-1][k]+abs(h[i]-num[j]))(若为上升序列则k<=j,若为下降序列则k>=j)

枚举k比较慢所以预处理一下

由于f[i]的取值只跟f[i-1]有关,所以运用滚动数字

program poj3666;
var
  n,i,j,k,tot,o,ans:longint;
  h,dl,num,min:array [0..2001] of longint;
  f:array [0..1,0..2001] of longint;

procedure swap (var a,b:longint);
var
  i:longint;
begin
  i:=a;
  a:=b;
  b:=i;
end;

procedure qsort (s,e:longint);
var
  i,j,k:longint;
begin
  if s>=e then exit;
  i:=s;
  j:=e;
  k:=dl[(s+e) div 2];
  while i<=j do
    begin
      while dl[i]<k do inc(i);
      while dl[j]>k do dec(j);
      if i>j then break;
      swap(dl[i],dl[j]);
      inc(i);
      dec(j);
    end;
  qsort(s,j);
  qsort(i,e);
end;

begin
  read(n);
  for i:=1 to n do
    read(h[i]);
  for i:=1 to n do
    dl[i]:=h[i];
  qsort(1,n);
  k:=0;
  dl[0]:=-maxlongint;
  for i:=1 to n do
    if dl[i]<>dl[k] then
      begin
        inc(tot);
        num[tot]:=dl[i];
        k:=i;
      end;
  ans:=maxlongint;
  fillchar(f,sizeof(f),0);
  o:=0;
  for i:=1 to n do
    begin
      o:=1-o;
      min[0]:=maxlongint;
      for j:=1 to tot do
        begin
          min[j]:=min[j-1];
          if f[1-o,j]<min[j] then min[j]:=f[1-o,j];
        end;
      for j:=1 to tot do
        f[o,j]:=min[j]+abs(h[i]-num[j]);
    end;
  for i:=1 to tot do
    if f[o,i]<ans then ans:=f[o,i];
  fillchar(f,sizeof(f),0);
  o:=0;
  for i:=1 to n do
    begin
      o:=1-o;
      min[tot+1]:=maxlongint;
      for j:=tot downto 1 do
        begin
          min[j]:=min[j+1];
          if f[1-o,j]<min[j] then min[j]:=f[1-o,j];
        end;
      for j:=1 to tot do
        f[o,j]:=min[j]+abs(h[i]-num[j]);
    end;
  for i:=1 to tot do
    if f[o,i]<ans then ans:=f[o,i];
  writeln(ans);
end.
【上篇】
【下篇】

抱歉!评论已关闭.