2336: [HNOI2011]任务调度 - BZOJ
一道随机算法的题目
随便用什么随机算法
首先我们可以想到枚举类型3的最终类型,然后再做
先贪心出一个较优的序列,首先我们知道肯定是在A机器上先做完类型1的事件再做类型2的事件,机器B也类似,因为这些没有等待时间,而他们做完了后续事情才能做
然后对类型1进行排序,按timeb为第一关键字降序(为了填补空隙,前面的越大排得就越紧密),按timea为第二关键字升序排序(尽量早点让类型1的B机器上的事先做),类型2的也类似
然后随机2000次左右(每次随机交换类型1的两个和类型2的两个)正确率就很高了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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.