2336: [HNOI2011]任务调度 - BZOJ

 

一道随机算法的题目

随便用什么随机算法

首先我们可以想到枚举类型3的最终类型,然后再做

先贪心出一个较优的序列,首先我们知道肯定是在A机器上先做完类型1的事件再做类型2的事件,机器B也类似,因为这些没有等待时间,而他们做完了后续事情才能做

然后对类型1进行排序,按timeb为第一关键字降序(为了填补空隙,前面的越大排得就越紧密),按timea为第二关键字升序排序(尽量早点让类型1的B机器上的事先做),类型2的也类似

然后随机2000次左右(每次随机交换类型1的两个和类型2的两个)正确率就很高了

  1 const
  2     maxn=22;
  3     inf=10000000;
  4 type
  5     node=record
  6       kind,a,b,time:longint;
  7     end;
  8 var
  9     a:array[0..maxn]of node;
 10     aa,bb,sa,sb:array[0..maxn]of longint;
 11     n,ans,ta,tb,numa,numb,suma,sumb:longint;
 12 
 13 function min(x,y:longint):longint;
 14 begin
 15     if x<y then exit(x);
 16     exit(y);
 17 end;
 18 
 19 function max(x,y:longint):longint;
 20 begin
 21     if x>y then exit(x);
 22     exit(y);
 23 end;
 24 
 25 procedure swap(var x,y:longint);
 26 var
 27     t:longint;
 28 begin
 29     t:=x;x:=y;y:=t;
 30 end;
 31 
 32 procedure init;
 33 var
 34     i:longint;
 35 begin
 36     read(n);
 37     for i:=1 to n do
 38       with a[i] do
 39         read(kind,a,b);
 40     ans:=inf;
 41 end;
 42 
 43 function geta:boolean;
 44 var
 45         k:longint;
 46 begin
 47     if numa>n then exit(false);
 48     if numa>suma then k:=bb[numa-suma]
 49     else k:=aa[numa];
 50     if (a[k].kind=1) or (a[k].time>0) then
 51     begin
 52       ta:=max(ta,a[k].time)+a[k].a;
 53       a[k].time:=ta;
 54       inc(numa);
 55       exit(true);
 56     end;
 57     exit(false);
 58 end;
 59 
 60 function getb:boolean;
 61 var
 62         k:longint;
 63 begin
 64     if numb>n then exit(false);
 65     if numb>sumb then k:=aa[numb-sumb]
 66     else k:=bb[numb];
 67     if (a[k].kind=2) or (a[k].time>0) then
 68     begin
 69       tb:=max(tb,a[k].time)+a[k].b;
 70       a[k].time:=tb;
 71       inc(numb);
 72       exit(true);
 73     end;
 74     exit(false);
 75 end;
 76 
 77 procedure get;
 78 var
 79     i,j,lastans:longint;
 80 begin
 81     suma:=0;
 82     sumb:=0;
 83     lastans:=inf;
 84     for i:=1 to n do
 85       if a[i].kind=1 then
 86         begin
 87           inc(suma);
 88           sa[suma]:=i;
 89         end
 90       else
 91         begin
 92           inc(sumb);
 93           sb[sumb]:=i;
 94         end;
 95     for i:=suma downto 2 do
 96       for j:=1 to i-1 do
 97         if (a[sa[j+1]].b>a[sa[j]].b) or ((a[sa[j+1]].b=a[sa[j]].b) and (a[sa[j+1]].a<a[sa[j]].a)) then swap(sa[j],sa[j+1]);
 98     for i:=sumb downto 2 do
 99       for j:=1 to i-1 do
100         if (a[sb[j+1]].a>a[sb[j]].a) or ((a[sb[j+1]].a=a[sb[j]].a) and (a[sb[j+1]].b<a[sb[j]].b)) then swap(sb[j],sb[j+1]);
101     for j:=1 to 2000 do
102       begin
103         aa:=sa;
104         bb:=sb;
105         if suma<>0 then
106         swap(aa[random(150000)mod suma+1],aa[random(150000)mod suma+1]);
107         if sumb<>0 then
108         swap(bb[random(150000)mod sumb+1],bb[random(150000)mod sumb+1]);
109         for i:=1 to n do
110           a[i].time:=0;
111         ta:=0;
112         tb:=0;
113         numa:=1;
114         numb:=1;
115         while (numa<=n) or (numb<=n) do
116           begin
117             if ta<tb then
118               begin
119                 if geta=false then getb;
120               end
121             else
122               if getb=false then geta;
123           end;
124         if lastans>=max(ta,tb) then
125         begin
126           lastans:=max(ta,tb);
127           ans:=min(lastans,ans);
128           sa:=aa;
129           sb:=bb;
130         end;
131     end;
132 end;
133 
134 procedure try(x:longint);
135 begin
136         if x=n+1 then get
137         else
138           if a[x].kind=3 then
139             begin
140               a[x].kind:=1;
141               try(x+1);
142               a[x].kind:=2;
143               try(x+1);
144               a[x].kind:=3;
145             end
146           else try(x+1);
147 end;
148 
149 begin
150     randomize;
151     init;
152     try(1);
153     write(ans);
154 end.
View Code

 

posted @ 2014-04-04 09:02  Randolph87  阅读(436)  评论(0编辑  收藏  举报