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

挖宝藏 treasures

2017年11月17日 ⁄ 综合 ⁄ 共 2196字 ⁄ 字号 评论关闭

挖宝藏

treasures/.in/.out/.pas/.exe

【题意】

在一个无限大的二维网格中有n处宝藏,给出每个宝藏的坐标(x[i],y[i])以及价值p[i],已知挖掘一个网格(x,y)需要满足<该点纵坐标y=-1>或<(x-1,y+1)(x,y+1)(x+1,y+1)三个网格都被挖掘过>,挖掘一个网格需要1代价,挖掘有宝藏的网格则可得到该宝藏的价值,求最大收益

【输入】

第一行一个数字n(n<=1000)

接下来n行每行三个数字表示一个宝藏(每个宝藏的横坐标大于等于-10000小于等于10000,纵坐标小于等于-1,价值不超过大于等于1小于等于1000000)

【输出】

输出一个数表示最大收益

动态规划

首先说一个思路上的误区,我看到这道题发现要挖掘一个点需要挖掘它之下的一个三角形,首先想到的是一行一行的处理,这不科学。

这道题应当竖着一列一列的处理,f[x][y]表示处理到第x行,最低点在y的最大收益

那么f[x][y]=max(f[x-1][y-1],f[x-1][y],f[x-1][y+1])+p[x][y] (p[x][y]表示第p列在-1..y的所有宝藏价值及挖掘费用之差)

由于x范围为20000,y范围为10000,20000*10000=200000000,时间上不允许

由于点比较少,所以采取离散化

首先枚举x坐标,然后求出在该列上的三角形边界上的点的纵坐标,排序后求p,便可以dp了

n<=1000的,相比于y优化了10倍,便可在规定时限内通过所有数据

program treasures;
type
  point=record
          x,y,p:longint;
        end;
  arr=array [-10001..0] of longint;
var
  tot,n,i,j,k,s,e,o,sum:longint;
  dl,root:array [0..1001] of point;
  zero:arr;
  f:array [0..1] of arr;

procedure swap (var a,b:longint);inline;
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].y;
  while i<=j do
    begin
      while dl[i].y>k do inc(i);
      while dl[j].y<k do dec(j);
      if i>j then break;
      swap(dl[i].x,dl[j].x);
      swap(dl[i].y,dl[j].y);
      swap(dl[i].p,dl[j].p);
      inc(i);
      dec(j);
    end;
  qsort(s,j);
  qsort(i,e);
end;

begin
  assign(input,'treasures.in');
  reset(input);
  assign(output,'treasures.out');
  rewrite(output);
  read(n);
  s:=maxlongint;
  e:=-maxlongint;
  for i:=1 to n do
    begin
      read(root[i].x,root[i].y,root[i].p);
      if root[i].x+(root[i].y+1)<s then s:=root[i].x+(root[i].y+1);
      if root[i].x-(root[i].y+1)>e then e:=root[i].x-(root[i].y+1);
    end;
  for i:=-10000 to 0 do
    zero[i]:=-maxlongint div 10;
  zero[0]:=0;
  o:=0;
  f[o]:=zero;
  tot:=0;
  for i:=s to e+1 do
    begin
      o:=1-o;
      f[o]:=zero;
      tot:=0;
      for j:=1 to n do
        if (root[j].x+(root[j].y+1)<=i)
        and(root[j].x-(root[j].y+1)>=i) then
          begin
            inc(tot);
            dl[tot].x:=i;
            dl[tot].y:=root[j].y+abs(root[j].x-i);
            if root[j].x=i then dl[tot].p:=root[j].p
                           else dl[tot].p:=0;
          end;
      qsort(1,tot);
      f[o,0]:=f[1-o,0];
      if f[1-o,-1]>f[o,0] then f[o,0]:=f[1-o,-1];
      k:=0;
      sum:=0;
      for j:=1 to tot do
        begin
          sum:=sum+dl[j].p+dl[j].y-k;
          k:=dl[j].y;
          if f[o,dl[j].y]<f[1-o,dl[j].y-1]+sum then
            f[o,dl[j].y]:=f[1-o,dl[j].y-1]+sum;
          if f[o,dl[j].y]<f[1-o,dl[j].y]+sum then
            f[o,dl[j].y]:=f[1-o,dl[j].y]+sum;
          if f[o,dl[j].y]<f[1-o,dl[j].y+1]+sum then
            f[o,dl[j].y]:=f[1-o,dl[j].y+1]+sum;
        end;
    end;
  writeln(f[o,0]);
  close(input);
  close(output);
end.
【上篇】
【下篇】

抱歉!评论已关闭.