挖宝藏 treasures

来源:互联网 发布:r计算相关系数矩阵 编辑:程序博客网 时间:2024/06/03 02:56

挖宝藏

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.


原创粉丝点击