jzoj 1570. 【普及模拟】射击 解题报告

题目描述

射击规则如下:

你最多可以射击4次,当然你也可以不射击,目标靶被分成N部分,每一部分的分值为P1,….,PN,你的总分为每次射击的分数之和,如果S不超过M,那你的分数就是S;否则如果S超过M,那么你的分数变为0。

写一个程序,给你每部分的分值以及M的值,计算你能得到的最大得分。

输入

   输入第一行是两个空格隔开的整数N(1<=N<=1000)和M(1<=M<=200000000=2*10^8),接下来N行每行一个整数Pi(1<=Pi<=100000000=10^8)。

输出

    输出一个整数表示你的最大得分。

样例输入

4 50

3

14

15

9

样例输出

48

数据范围限制

提示

【样例输入输出】


















dart.in

dart.out

4 50

3

14

15

9

48

3 21

16

11

2

20


【数据范围】

20%的N<=100

50%的N<=300

代码如下: 方法自己领悟吧。。。千万不要觉得这是背包,因为它有后效性。。

var
 n,m,i,j,k:longint;
 a:array[1..2000000]of int64;
 ans:int64;
procedure qsort(l,r:longint);
var i,j,m,t:longint;
begin
 if l>=r then exit;
 i:=l; j:=r; m:=a[(i+j) div 2];
repeat
 while a[i]do inc(i);
 while a[j]>m do dec(j);
  if i<=j then begin
   t:=a[i]; a[i]:=a[j]; a[j]:=t;
   inc(i); dec(j);
  end;
 until i>j;
 qsort(l,j);
 qsort(i,r);
end;

begin
 assign(input,'dart.in'); reset(input);
 assign(output,'dart.out');rewrite(output);
 readln(n,m);
 for i:=1 to n do
  readln(a[i]);
  for i:=1 to n do
   for j:=1 to n do
    begin
     inc(k);
     a[n+k]:=a[i]+a[j];
    end;
 qsort(1,n+k);
 i:=1;   j:=n+k;
 while i<=j do
  begin
   if a[i]+a[j]<=m then begin if a[i]+a[j]>ans then ans:=a[i]+a[j];  inc(i); end
   else dec(j);
  end;
 write(ans);
 close(input); close(output);
end.

你可能感兴趣的:(水法)