1. 程式人生 > >jzoj 2549. 【NOIP2011模擬9.4】家庭作業

jzoj 2549. 【NOIP2011模擬9.4】家庭作業

題目描述

老師在開學第一天就把所有作業都佈置了,每個作業如果在規定的時間內交上來的話才有學分。每個作業的截止日期和學分可能是不同的。例如如果一個作業學分為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學分,其中一個完成作業的次序為2,6,3,1,7,5,4,注意可能d還有其他方法。
  你的任務就是找到一個完成作業的順序獲得最大學分。

輸入

 第一行一個整數N,表示作業的數量。接下來N行,每行包括兩個整數,第一個整數表示作業的完成期限,第二個數表示該作業的學分。

輸出

 輸出一個整數表示可以獲得的最大學分。保證答案不超過longint

思路

。。。我也不知道怎麼講詳情請看 http://my.csdn.net/a_loud_name( 某三班同學的部落格)
但是我還是來嘗試解釋一下,首先按照學分從大到小排序,然後開一個數組s,s[i,2]來記錄這個時間是不是被佔用了,s[i,1]開始是指向前一位的指標
每次取學分最大的值放入距離其結束時間最近的地方,這時就要用到遞迴來尋找最近的空閒時間點然後在遞迴的過程中將所有已經佔用的點的指標全部轉移到找到的空閒點的指標指的位置上,然後如果找到了第0位是就說明放不下了,直接跳過當前任務,進行下一個,所以在開始時要將s[0,2]賦為1,這樣就直接跳過了,一直做到全部做完為止每找到一個可以做的就直接ans+1就可以了

var
  a:array[0..1000000,1..2] of longint;
  s:array[0..1000000,1..2] of longint;
  i,j,k,n,m,x,y,max,ans:longint;
procedure sort(l,r:longint);
var
  i,j,mid,t:longint;
begin
  i:=l; j:=r;
  mid:=a[(r+l) div 2,2];
  repeat
    while a[i,2]>mid do inc(i);
    while a[j,2]<mid do dec(j);
    if i<=j then
begin t:=a[i,1]; a[i,1]:=a[j,1]; a[j,1]:=t; t:=a[i,2]; a[i,2]:=a[j,2]; a[j,2]:=t; inc(i); dec(j); end; until i>j; if i<r then sort(i,r); if j>l then sort(l,j); end; function find(x:longint):longint; begin if (s[x,1]=0) or (s[x,2]=0) then exit(x); s[x,1]:=find(s[x,1]); exit(s[x,1]) end; begin assign(input,'10.in'); reset(input); s[0,2]:=1; readln(n); for i:=1 to n do begin readln(a[i,1],a[i,2]); end; sort(1,n); for i:=1 to n do s[i,1]:=i-1; for i:=1 to n do begin if s[a[i,1],2]=0 then x:=a[i,1] else x:=find(s[a[i,1],1]); if s[x,2]=0 then begin s[x,2]:=1; ans:=ans+a[i,2]; end; end; writeln(ans); close(input); end.