【NOIP2018复习】可爱精灵宝贝(区间DP)

1228.可爱精灵宝贝

时间限制:2000MS内存限制:524000KB

题目描述

Branimirko是一个对可爱精灵宝贝十分痴迷的玩家。最近,他闲得没事组织了一场捉精灵的游戏。游戏在一条街道上举行,街道上一侧有一排房子,从左到右房子标号由1到n。
刚开始玩家在k号房子前。有m个精灵,第i只精灵在第A[i]栋房子前,分值是B[i],以及它在T[i]秒内(含)存在,之后消失。Branimirko可以选择移动至相邻的房子,耗时1秒。抓住精灵不需要时间,精灵被抓住后消失。时间从第1秒开始。Branimirko能最多获得多少分值和。
 

输入

输入的第1行为三个正整数n,k,m。
接下来m行描述精灵的信息,分别为A[i],B[i],T[i]。

输出

输出Branimirko能最多获得多少分值和。

输入样例复制

10 5 4
1 30 4
3 5 7
7 10 12
9 100 23

输出样例复制

115

说明

Data Constraint 20%的数据:m≤10 40%的数据:m≤20 k≤n≤1000,m≤100,A[i] ≤N,B[i] ≤100,T[i] ≤2000,所有数为正整数。   Hint 很遗憾,它恰好不能抓住在一号房子前的精灵。 如果T[1]改成5,答案就是145


题解:f[t,l,r,0/1]表示在t秒内[l,r]中玩家在l或r的最大分值
          因为二维不能判断能否来回走,所以要三维
         将点离散
         90分未AC

const

  maxn=1000;

var

  f:array[0..2000,0..100,0..100,0..1]of longint;

  a,e:array[0..105,1..3]of longint;

  n,k,mt,m,t,po,l,r,ans:longint;

function max(a,b:longint):longint;

begin

  if a>b then exit(a) else exit(b);

end;

procedure qsort(l,r:longint);

var

  i,j,key:longint;

begin

  if l>r then exit;

  i:=l;j:=r;

  key:=a[(l+r)div 2,1];

  repeat

    while a[i,1]<key do inc(i);

    while a[j,1]>key do dec(j);

    if i<=j then

    begin

      a[0]:=a[i];a[i]:=a[j];a[j]:=a[0];

      inc(i);dec(j);

    end;

  until i>j;

  qsort(l,j);

  qsort(i,r);

end;

function dis(x,y:longint):longint;

begin

  dis:=abs(a[x,1]-a[y,1]);

end;

procedure init;

var

  i,j:longint;

begin

  readln(n,k,m);

  for i:=1 to m do

  begin

    readln(a[i,1],a[i,2],a[i,3]);

    a[i,3]:=a[i,3]-1;

    mt:=max(mt,a[i,3]);

  end;

  qsort(1,m);

  a[m+1,1]:=maxlongint;

  for i:=1 to m do

  begin

    if a[i,1]=k then

    begin

      po:=i;

      break;

    end;

    if (i=1)and(a[i,1]>k) then

    begin

      for j:=m+1 downto 2 do

        a[j]:=a[j-1];

      a[1,1]:=k;a[1,2]:=0;a[1,3]:=0;

      po:=1;

      break;

    end;

    if (a[i,1]<k)and(a[i+1,1]>k) then

    begin

      for j:=m+1 downto i+2 do

        a[j]:=a[j-1];

      po:=i+1;

      a[po,1]:=k;a[po,2]:=0;a[po,3]:=0;

      m:=m+1;

      break;

    end;

  end;

  for i:=0 to mt do

    for j:=0 to 100 do

      for k:=0 to 100 do

      begin

        f[i,j,k,0]:=-maxlongint;

        f[i,j,k,1]:=-maxlongint;

      end;

  f[0,po,po,0]:=0;

  f[0,po,po,1]:=0;

{  for i:=1 to mt do

  begin

    if i<=a[po,3] then f[i,po,po,0]:=a[po,2] else f[i,po,po,0]:=0;

    if i<=a[po,3] then f[i,po,po,1]:=a[po,2] else f[i,po,po,1]:=0;

  end;   }

  for i:=po-1 downto 1 do

  begin

    f[dis(i,po),i,po,0]:=f[dis(i+1,po),i+1,po,0];

    if a[i,3]>=dis(i,po) then inc(f[dis(i,po),i,po,0],a[i,2]);

    ans:=max(ans,f[dis(i,po),i,po,0]);

  end;

  for i:=po+1 to m do

  begin

    f[dis(i,po),po,i,1]:=f[dis(i-1,po),po,i-1,1];

    if a[i,3]>=dis(i,po) then inc(f[dis(i,po),po,i,1],a[i,2]);

    ans:=max(ans,f[dis(i,po),po,i,1]);

  end;

end;

begin

  init;

  for t:=1 to mt do

  begin

    for l:=1 to po-1 do

      for r:=po+1 to m do

      begin

        f[t,l,r,0]:=max(f[max(t-dis(l,l+1),0),l+1,r,0],f[max(t-dis(l,r),0),l+1,r,1]);

        if a[l,3]>=t then inc(f[t,l,r,0],a[l,2]);

        f[t,l,r,1]:=max(f[max(t-dis(r-1,r),0),l,r-1,1],f[max(t-dis(r,l),0),l,r-1,0]);

        if a[r,3]>=t then inc(f[t,l,r,1],a[r,2]);

        ans:=max(ans,f[t,l,r,0]);

        ans:=max(ans,f[t,l,r,1]);

      end;

  end;

  writeln(ans);

end.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值