• 【BZOJ1061】志愿者招募(单纯形,对偶性)


    题意:

    这个项目需要N 天才能完成,其中第i 天至少需要
    Ai 个人。 布布通过了解得知,一共有M 类志愿者可以招募。其中第i 类可以从第Si 天工作到第Ti 天,招募费用
    是每人Ci 元。新官上任三把火,为了出色地完成自己的工作,布布希望用尽量少的费用招募足够的志愿者,但这
    并不是他的特长!于是布布找到了你,希望你帮他设计一种最优的招募方案。
    第一行包含两个整数N, M,表示完成项目的天数和可以招募的志愿者的种类。 接下来的一行中包含N 个非负
    整数,表示每天至少需要的志愿者人数。 接下来的M 行中每行包含三个整数Si, Ti, Ci,含义如上文所述。为了
    方便起见,我们可以认为每类志愿者的数量都是无限多的。
    1 ≤ N ≤ 1000,1 ≤ M ≤ 10000,题目中其他所涉及的数据均 不超过2^31-1。
    思路:线性规划的对偶性 参见《算导》29章

    全幺模矩阵可以保证至少有一组整数解

    就是a[i,j]取值只为-1,0,1的矩阵

    这个线性规划根据对偶性等价于

     1 const eps=1e-8;
     2 var a:array[0..10000,0..1000]of double;
     3     idx,idy,q:array[0..10000]of longint;
     4     b,c:array[0..10000]of double;
     5     n,m,i,j,op,x,y:longint;
     6     mn,p:double;
     7 
     8 procedure swap(var x,y:longint);
     9 var t:longint;
    10 begin
    11  t:=x; x:=y; y:=t;
    12 end;
    13 
    14 procedure povit(x,y:longint);
    15 var i,j,tot:longint;
    16     tmp:double;
    17 
    18 begin
    19  swap(idx[y],idy[x]);
    20  tmp:=a[x,y]; a[x,y]:=1/a[x,y];
    21  for i:=0 to n do
    22   if y<>i then a[x,i]:=a[x,i]/tmp;
    23  tot:=0;
    24  for i:=0 to n do
    25   if (i<>y)and((a[x,i]>eps)or(a[x,i]<-eps)) then
    26   begin
    27    inc(tot); q[tot]:=i;
    28   end;
    29  for i:=0 to m do
    30  begin
    31   if (x=i)or((a[i,y]<eps)and(a[i,y]>-eps)) then continue;
    32   for j:=1 to tot do a[i,q[j]]:=a[i,q[j]]-a[x,q[j]]*a[i,y];
    33   a[i,y]:=-a[i,y]/tmp;
    34  end;
    35 end;
    36 
    37 function min(x,y:longint):longint;
    38 begin
    39  if x<y then exit(x);
    40  exit(y);
    41 end;
    42 
    43 begin
    44  assign(input,'bzoj1061.in'); reset(input);
    45  assign(output,'bzoj1061.out'); rewrite(output);
    46  randomize;
    47  readln(n,m);
    48  for i:=1 to n do read(c[i]);
    49  for i:=1 to m do
    50  begin
    51   readln(x,y,b[i]);
    52   for j:=x to y do a[i,j]:=1;
    53  end;
    54 
    55 
    56  for i:=1 to n do a[0,i]:=c[i];
    57  for i:=1 to m do a[i,0]:=b[i];
    58  for i:=1 to n do idx[i]:=i;
    59  for i:=1 to m do idy[i]:=i+n;
    60  while true do
    61  begin
    62   x:=0; y:=0;
    63   for i:=1 to m do
    64    if (a[i,0]<-eps)and((x=0)or(random(2)=1)) then x:=i;
    65   if x=0 then break;
    66   for i:=1 to n do
    67    if (a[x,i]<-eps)and((y=0)or(random(2)=1)) then y:=i;
    68   if y=0 then break;
    69   povit(x,y);
    70  end;
    71  while true do
    72  begin
    73   x:=0; y:=0; mn:=1e15;
    74   for i:=1 to n do
    75    if a[0,i]>eps then begin y:=i; break; end;
    76   if y=0 then break;
    77   for i:=1 to m do
    78    if (a[i,y]>eps)and(a[i,0]/a[i,y]<mn) then
    79    begin
    80     mn:=a[i,0]/a[i,y]; x:=i;
    81    end;
    82   if x=0 then break;
    83   povit(x,y);
    84  end;
    85  writeln(-a[0,0]:0:0);
    86  close(input);
    87  close(output);
    88 end.
  • 相关阅读:
    Date
    Math
    封装实参的对象 arguments
    函数方法call()和apply()
    执行上下文栈
    原型(prototype属性)和原型链。 重要!!!
    android studio for Mac快捷键大全
    软件的横竖屏切换
    Android XML文件中@id和@+id的区别
    java中的Iterator<E>
  • 原文地址:https://www.cnblogs.com/myx12345/p/6484657.html
Copyright © 2020-2023  润新知