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

Sue 的小球 ball

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

三、Sue 的小球
(ball.pas/c/cpp,限时0.5 秒,内存256M)
【题目描述】
Sue 和Sandy 最近迷上了一个电脑游戏,这个游戏的故事发在美丽神秘并且充满刺
激的大海上,Sue 有一支轻便小巧的小船。然而,Sue 的目标并不是当一个海盗,而是
要收集空中漂浮的彩蛋,Sue 有一个秘密武器,只要她将小船划到一个彩蛋的正下方,
然后使用秘密武器便可以在瞬间收集到这个彩蛋。然而,彩蛋有一个魅力值,这个魅力
值会随着彩蛋在空中降落的时间而降低,Sue 要想得到更多的分数,必须尽量在魅力值
高的时候收集这个彩蛋,而如果一个彩蛋掉入海中,它的魅力值将会变成一个负数,但
这并不影响Sue 的兴趣,因为每一个彩蛋都是不同的,Sue 希望收集到所有的彩蛋。
然而Sandy 就没有Sue 那么浪漫了,Sandy 希望得到尽可能多的分数,为了解决这
个问题,他先将这个游戏抽象成了如下模型:

以Sue 的初始位置所在水平面作为x 轴。

一开始空中有N 个彩蛋,对于第i 个彩蛋,他的初始位置用整数坐标(xi, yi)表
示,游戏开始后,它匀速沿y 轴负方向下落,速度为vi 单位距离/单位时间。Sue 的初始
位置为(x0, 0),Sue 可以沿x 轴的正方向或负方向移动,Sue 的移动速度是1 单位距离
/单位时间,使用秘密武器得到一个彩蛋是瞬间的,得分为当前彩蛋的y 坐标的千分之
一。
现在,Sue 和Sandy 请你来帮忙,为了满足Sue 和Sandy 各自的目标,你决定在收
集到所有彩蛋的基础上,得到的分数最高。
【输入文件】
第一行为两个整数N, x0 用一个空格分隔,表示彩蛋个数与Sue 的初始位置。
第二行为N 个整数xi,每两个数用一个空格分隔,第i 个数表示第i 个彩蛋的初始
横坐标。

第三行为N 个整数yi,每两个数用一个空格分隔,第i 个数表示第i 个彩蛋的初始
纵坐标。
第四行为N 个整数vi,每两个数用一个空格分隔,第i 个数表示第i 个彩蛋匀速沿
y 轴负方向下落的的速度。
【输出文件】
一个实数,保留三位小数,为收集所有彩蛋的基础上,可以得到最高的分数。
【样例】
输入样例(ball.in 的内容):
3 0
-4 -2 2
22 30 26
1 9 8
输出样例(ball.out 的内容):
0.000
【数据范围】
N<=20,对于30%的数据。
N<=1000,对于100%的数据。
-10^4 <= xi,yi,vi <= 10^4,对于100%的数据。

动态规划

首先可以明确的是可以将x0左边和右边的彩蛋分组

按距离x0距离的顺序排序,存入两个队列中

y之和为最多达到的分数

用f[0][i][j]表示当前在队列1的i位置,队列2已该走j位置的分数减小最小值

用f[1][i][j]表示当前在队列2的j位置,队列1已该走i位置的分数减小最小值

转移方程为

f[0,i,j]=min(f[0,i-1,j]+(w1[i]+w2[j])*(s1[i-1].x-s1[i].x),f[1,i,j-1]+(w1[i]+w2[j])*(s2[j-1].x-s1[i].x))

f[1,i,j]=min(f[0,i-1,j]+(w1[i]+w2[j])*(s2[j].x-s1[i-1].x),f[1,i,j-1]+(w1[i]+w2[j])*(s2[j].x-s2[j-1].x))

当前在y坐标之和减去min(<当前在队列1队尾,队列2已走完的分数减小最小值>,<当前在队列2队尾,队列1已走完的分数减小最小值>)

测试数据

http://mail.qq.com/cgi-bin/ftnExs_download?k=716635352cf2cbcd6241402a1865011d065605050755041d1800020354500002554b0c0652541906555f0c180f5057011a560707045306510257000c00653c3255075959191755403720&t=exs_ftn_download&code=7f557e42

program ball;
const
  thu:int64=1000;
type
  point=record
          x,v:longint;
        end;
var
  n,x0,i,j,k,t1,t2,d1,d2:longint;
  ans:int64;
  s1,s2,bal:array [0..1001] of point;
  f:array [0..1,0..1001,0..1001] of int64;
  w1,w2:array [0..1001] of int64;

procedure swap (var a,b:point);
var
  i:point;
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:=bal[(s+e) div 2].x;
  while i<=j do
    begin
      while bal[i].x<k do inc(i);
      while bal[j].x>k do dec(j);
      if i>j then break;
      swap(bal[i],bal[j]);
      inc(i);
      dec(j);
    end;
  qsort(s,j);
  qsort(i,e);
end;

begin
  assign(input,'ball.in');
  reset(input);
  assign(output,'ball.out');
  rewrite(output);
  read(n,x0);
  ans:=0;
  for i:=1 to n do
    read(bal[i].x);
  for i:=1 to n do
    begin
      read(k);
      ans:=ans+k;
    end;
  for i:=1 to n do
    read(bal[i].v);
  qsort(1,n);
  t1:=0;
  d1:=0;
  for i:=n downto 1 do
    if bal[i].x<x0 then
      begin
        if (t1>0)and(bal[i].x=s1[t1].x) then
          s1[t1].v:=s1[t1].v+bal[i].v
                                        else
          begin
            inc(t1);
            s1[t1]:=bal[i];
          end;
        d1:=d1+bal[i].v;
      end;
  t2:=0;
  d2:=0;
  for i:=1 to n do
    if bal[i].x>x0 then
      begin
        if (t2>0)and(bal[i].x=s2[t2].x) then
          s2[t2].v:=s2[t2].v+bal[i].v
                                        else
          begin
            inc(t2);
            s2[t2]:=bal[i];
          end;
        d2:=d2+bal[i].v;
      end;
  fillchar(f,sizeof(f),63);
  s1[0].x:=x0;
  for i:=t1 downto 0 do
    w1[i]:=w1[i+1]+s1[i].v;
  for i:=t2 downto 1 do
    w2[i]:=w2[i+1]+s2[i].v;
  s1[t1+1].x:=s1[t1].x;
  s2[t2+1].x:=s2[t2].x;
  f[0,0,1]:=0;
  for i:=0 to t1+1 do
    for j:=1 to t2+1 do
      begin
        if (i=t1+1)and(j=t2+1) then continue;

        if (i<>t1+1)and(i>0)and(f[0,i,j]>f[0,i-1,j]+(w1[i]+w2[j])*(s1[i-1].x-s1[i].x)) then
          f[0,i,j]:=f[0,i-1,j]+(w1[i]+w2[j])*(s1[i-1].x-s1[i].x);

        if (j<>t2+1)and(i>0)and(f[1,i,j]>f[0,i-1,j]+(w1[i]+w2[j])*(s2[j].x-s1[i-1].x)) then
          f[1,i,j]:=f[0,i-1,j]+(w1[i]+w2[j])*(s2[j].x-s1[i-1].x);

        if (i<>t1+1)and(j>1)and(f[0,i,j]>f[1,i,j-1]+(w1[i]+w2[j])*(s2[j-1].x-s1[i].x)) then
          f[0,i,j]:=f[1,i,j-1]+(w1[i]+w2[j])*(s2[j-1].x-s1[i].x);

        if (j<>t2+1)and(j>1)and(f[1,i,j]>f[1,i,j-1]+(w1[i]+w2[j])*(s2[j].x-s2[j-1].x)) then
          f[1,i,j]:=f[1,i,j-1]+(w1[i]+w2[j])*(s2[j].x-s2[j-1].x);

      end;
  if ans-f[0,t1,t2+1]>ans-f[1,t1+1,t2] then ans:=ans-f[0,t1,t2+1]
                                       else ans:=ans-f[1,t1+1,t2];
  writeln(ans/1000:0:3);
  close(input);
  close(output);
end.

【上篇】
【下篇】

抱歉!评论已关闭.