【NOI2008】 志愿者招募

题目描述
志愿者招募
【问题描述】
申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的
主管。布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志
愿者。经过估算,这个项目需要 N 天才能完成,其中第 i 天至少需要 Ai 个人。
布布通过了解得知,一共有 M 类志愿者可以招募。其中第 i 类可以从第 Si 天工
作到第 Ti 天,招募费用是每人 Ci 元。新官上任三把火,为了出色地完成自己的
工作,布布希望用尽量少的费用招募足够的志愿者,但这并不是他的特长!于是
布布找到了你,希望你帮他设计一种最优的招募方案。
【输入格式】
输入文件 employee.in 的第一行包含两个整数 N, M,表示完成项目的天数和
可以招募的志愿者的种类。
接下来的一行中包含 N 个非负整数,表示每天至少需要的志愿者人数。
接下来的 M 行中每行包含三个整数 Si, Ti, Ci,含义如上文所述。为了方便起
见,我们可以认为每类志愿者的数量都是无限多的。
【输出格式】
输入文件 employee.out 中仅包含一个整数,表示你所设计的最优方案的总费
用。
【输入样例】
33
234
122
235
332
【输出样例】
14
【样例说明】
招募 3 名第一类志愿者和 4 名第三类志愿者。
【数据规模和约定】
30%的数据中,1 ≤ N, M ≤ 10,1 ≤ Ai ≤ 10;
100%的数据中,1 ≤ N ≤ 1000,1 ≤ M ≤ 10000,题目中其他所涉及的数据均
不超过 231-1

 

题解

 

解法1:搜索
 1 (*
 2     *Problem:    NOI2008 自愿者招募
 3     *Author :    Chen Yang
 4     *Time   :    2012.5.18
 5     *State  :    30分
 6     *Memo    :    搜索
 7 *)
 8 program employee;
 9 const maxn=2020;
10 type
11   ty=record
12     x,y,v:longint;
13   end;
14 
15 var
16   n,m,ans:longint;
17   g,now,cnt:array[0..maxn] of longint;
18   t:array[0..maxn] of ty;
19 //========================
20 procedure built;
21 var
22   i,j:longint;
23 begin
24   read(n,m);
25   for i:=1 to n do read(g[i]);
26   for i:=1 to m do
27   begin
28     read(t[i].x,t[i].y,t[i].v);
29     for j:=t[i].x to t[i].y do inc(cnt[j]);
30   end;
31 end;
32 //========================
33 procedure find(x,v:longint);
34 var
35   i,j,k,max:longint;
36 begin
37   if v>=ans then exit;
38   if x=m+1 then
39   begin
40     if ans>v then ans:=v;
41     exit;
42   end;
43   max:=0;
44   for j:=t[x].x to t[x].y do
45   begin
46     dec(cnt[j]);
47     if max<g[j] then max:=g[j];
48   end;
49   for i:=max downto 0 do
50   begin
51     for j:=t[x].x to t[x].y do
52     begin
53       inc(now[j],i);
54       if (cnt[j]=0)and(now[j]<g[j]) then
55       begin
56         for k:=t[x].x to j do dec(now[k],i);
57         for k:=t[x].x to t[x].y do inc(cnt[k]);
58         exit;
59       end;
60     end;
61     find(x+1,v+t[x].v*i);
62     for j:=t[x].x to t[x].y do dec(now[j],i);
63   end;
64   for j:=t[x].x to t[x].y do inc(cnt[j]);
65 end;
66 //========================
67 begin
68   assign(input,'employee.in'); reset(input);
69   assign(output,'employee.out'); rewrite(output);
70   built;
71   ans:=maxlongint;
72   find(1,0);
73   writeln(ans);
74   close(input); close(output);
75 end.

 

解法2:网络流
  1 (*
  2     *Problem:    NOI2008 自愿者招募
  3     *Author :    Chen Yang
  4     *Time   :    2012.5.18
  5     *State  :    AC
  6     *Memo    :    网络流
  7 *)
  8 program employee;
  9 uses math;
 10 const max=100000000;
 11       maxn=2020;
 12 type
 13   ty1=^ty2;
 14   ty2=record
 15     x,f,v,fa:longint;
 16     next,up:ty1;
 17   end;
 18 
 19 var
 20   n,m,s,t,flow,tot,ans:longint;
 21   first,fa:array[0..maxn] of ty1;
 22   dui,dis,mflow:array[0..maxn] of longint;
 23   get:array[0..maxn] of boolean;
 24 //==================
 25 procedure insert(x,y,f,v:longint);          inline;
 26 var
 27   p,q:ty1;
 28 begin
 29   new(p);
 30   p^.x:=y; p^.f:=f; p^.v:=v; p^.fa:=x;
 31   p^.next:=first[x]; first[x]:=p;
 32   new(q);
 33   q^.x:=x; q^.f:=0; q^.v:=-v; q^.fa:=y;
 34   q^.next:=first[y]; first[y]:=q;
 35   p^.up:=q; q^.up:=p;
 36 end;
 37 //==================
 38 procedure built;
 39 var
 40   i,x,y,z:longint;
 41 begin
 42   read(n,m);
 43   s:=0; t:=n+2; y:=0;
 44   for i:=1 to n do
 45   begin
 46     read(x);
 47     if x-y>0 then begin insert(s,i,x-y,0); inc(tot,x-y); end
 48     else if x-y<0 then insert(i,t,y-x,0);
 49     y:=x;
 50     insert(i+1,i,max,0);
 51   end;
 52   insert(n+1,t,x,0);
 53   for i:=1 to m do
 54   begin
 55     read(x,y,z);
 56     insert(x,y+1,max,z);
 57   end;
 58 end;
 59 //==================
 60 procedure spfa;
 61 var
 62   l,r,x:longint;
 63   p:ty1;
 64 begin
 65   fillchar(get,sizeof(get),false);
 66   fillchar(dis,sizeof(dis),$7);
 67   fillchar(mflow,sizeof(mflow),$7);
 68   l:=0; r:=1; dui[1]:=s; dis[s]:=0;
 69   while l<>r do
 70   begin
 71     inc(l); if l>maxn then l:=0;
 72     x:=dui[l]; get[x]:=false;
 73     p:=first[x];
 74     while p<>nil do
 75     begin
 76       if (p^.f>0) and (dis[p^.x]>dis[x]+p^.v) then
 77       begin
 78         dis[p^.x]:=dis[x]+p^.v; mflow[p^.x]:=min(mflow[x],p^.f);
 79         fa[p^.x]:=p;
 80         if not get[p^.x] then
 81         begin
 82           get[p^.x]:=true;
 83           inc(r); if r>maxn then r:=0;
 84           dui[r]:=p^.x;
 85         end;
 86       end;
 87       p:=p^.next;
 88     end;
 89   end;
 90   inc(flow,mflow[t]); inc(ans,mflow[t]*dis[t]);
 91   p:=fa[t];
 92   while p<>nil do
 93   begin
 94     dec(p^.f,mflow[t]);
 95     inc(p^.up^.f,mflow[t]);
 96     p:=fa[p^.fa];
 97   end;
 98 end;
 99 //==================
100 begin
101   assign(input,'employee.in'); reset(input);
102   assign(output,'employee.out'); rewrite(output);
103   built;
104   while flow<tot do spfa;
105   writeln(ans);
106   close(input); close(output);
107 end.
posted @ 2012-05-22 17:48  datam  阅读(277)  评论(0编辑  收藏  举报