家庭作业

本文介绍了一种通过合理安排作业提交顺序以最大化获取学分的算法。该算法使用了贪心策略,并借助堆来维护当前最优解,适用于作业数量巨大且期限各异的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

  老师在开学第一天就把所有作业都布置了,每个作业如果在规定的时间内交上来的话才有学分。每个作业的截止日期和学分可能是不同的。例如如果一个作业学分为10,要求在6天内交,那么要想拿到这10学分,就必须在第6天结束前交。
  每个作业的完成时间都是只有一天。例如,假设有7次作业的学分和完成时间如下:
  作业号 1 2 3 4 5 6 7 
  期限 1 1 3 3 2 2 6 
  学分 6 7 2 1 4 5 1 
  最多可以获得15学分,其中一个完成作业的次序为2631754,注意可能d还有其他方法。
  你的任务就是找到一个完成作业的顺序获得最大学分。

Input

  第一行一个整数N,表示作业的数量。接下来N行,每行包括两个整数,第一个整数表示作业的完成期限,第二个数表示该作业的学分。

Output

  输出一个整数表示可以获得的最大学分。保证答案不超过longint范围。

Sample Input

7

1 6

1 7

3 2

3 1

2 4

2 5

6 1

Sample Output

        15

DataConstraint

Hint

【数据规模】
  对于所有数据,N<=1000000,作业的完成期限均小于700000
  对于部分数据,N<=1000
  对于部分数据,N<=10000
  对于部分数据,N<=100000
  对于部分数据,作业的完成期限小于100
  对于部分数据,作业的完成期限小于1000

 

分析:

一看题,我就有种熟悉的感觉(似曾相识啊!!!据说某学霸可以告诉你答案)?于是我又从贪心的角度思考,呵呵,好像贪心是可以对的,只需按时间排序,然后记录选了几个,如果在期限内就直接加入数组,如果不在就选数组内最小的数与之比较,将大的存入数组,最后求和即是答案。于是,我就加了堆来维护数组最小值。

 

程序:

const
 maxn=1000001;
var
 a:array [0..maxn] of longint;
 x,y:array [0..maxn] of longint;
 ans,i,j,t,n:longint;
procedure qsort(l,r:longint);
  var
   i,j,key,temp:longint;
  begin
   if l>=r then exit;
   i:=l;j:=r;
   key:=x[l+random(r-l+1)];
  repeat
   while  (x[i]<key) do inc(i);
   while  (x[j]>key) do dec(j);
   if i<=j then
    begin
     temp:=x[i];x[i]:=x[j];x[j]:=temp;
     temp:=y[i];y[i]:=y[j];y[j]:=temp;
     inc(i);dec(j);
    end;
  until i>j;
  qsort(l,j);
  qsort(i,r);
 end;

procedure insert1(x:longint);
var i,temp:longint;
 begin
  inc(t);
  a[t]:=x;
  i:=t;
  while (i>1) and (a[i]>a[i shr 1]) do
   begin
    temp:=a[i];
    a[i]:=a[i shr 1];
    a[i shr 1]:=temp;
    i:=i shr 1;
   end;
 end;

function delete1:longint;
var i,temp,s:longint;
    flag:boolean;
begin
  delete1:=a[1];
  a[1]:=a[t];
  dec(t);
  i:=1;
  flag:=true;
  while flag and (i shl 1<=t) do
   begin
    if (i shl 1+1>t) or (a[i shl 1]>a[i shl 1+1]) then s:=i shl 1
                                                  else s:=i shl 1+1;
    if a[s]>a[i] then
     begin
      temp:=a[i];
      a[i]:=a[s];
      a[s]:=temp;
      i:=s;
     end
    else flag:=false;
   end;
 end;

begin
 readln(n);
 for i:=1 to n do
  readln(x[i],y[i]);
 qsort(1,n);
 j:=n;
 for i:=x[n] downto 1 do
  begin
   while (x[j]>=i) and (j>=1) do
    begin
     insert1(y[j]);
     dec(j);
    end;
   if t>=1 then ans:=ans+delete1;
  end;
 writeln(ans);
end.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值