• bzoj1061 [Noi2008]志愿者招募


    Description

      申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管。布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者。经过估算,这个项目需要N 天才能完成,其中第i 天至少需要Ai 个人。 布布通过了解得知,一共有M 类志愿者可以招募。其中第i 类可以从第Si 天工作到第Ti 天,招募费用是每人Ci 元。新官上任三把火,为了出色地完成自己的工作,布布希望用尽量少的费用招募足够的志愿者,但这并不是他的特长!于是布布找到了你,希望你帮他设计一种最优的招募方案。

    Input

      第一行包含两个整数N, M,表示完成项目的天数和可以招募的志愿者的种类。 接下来的一行中包含N 个非负整数,表示每天至少需要的志愿者人数。 接下来的M 行中每行包含三个整数Si, Ti, Ci,含义如上文所述。为了方便起见,我们可以认为每类志愿者的数量都是无限多的。

    Output

      仅包含一个整数,表示你所设计的最优方案的总费用。

    Sample Input

    3 3
    2 3 4
    1 2 2
    2 3 5
    3 3 2

    Sample Output

    14

    HINT

    1 ≤ N ≤ 1000,1 ≤ M ≤ 10000,题目中其他所涉及的数据均 不超过2^31-1。

    正解:不知道。。据说原本的正解线性规划被hack掉了。。

    然而我连线性规划都不会,所以写了一个naive的费用流。。学了以后再来填坑吧。。填坑了,见下面的代码。。

    考虑从原点向第0天连容量为inf,费用为0的边,第i天向第i+1天连容量为inf-a[i],费用为0的边,我们把这条线称之为主线。第n天向汇点连容量为inf,费用为0的边。对于每一段区间,从第s-1天到第t天连容量为inf,费用为c的边,我们把这条线称为副线。那么跑费用流时,主线上的堵塞流就自动地转移到副线上,同时,副线又因为有费用,那么我们就可以算出最小的费用了。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <complex>
     5 #include <cstring>
     6 #include <cstdlib>
     7 #include <cstdio>
     8 #include <vector>
     9 #include <cmath>
    10 #include <queue>
    11 #include <stack>
    12 #include <map>
    13 #include <set>
    14 #define inf (1<<29)
    15 #define il inline
    16 #define RG register
    17 #define ll long long
    18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    19 
    20 using namespace std;
    21 
    22 struct edge{ int nt,to,flow,cap,cost; }g[30010];
    23 
    24 
    25 queue <int> Q;
    26 int head[1010],dis[1010],flow[1010],fa[1010],p[1010],a[1010],n,m,S,T,num=1,cost;
    27 
    28 il int gi(){
    29     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    30     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
    31 }
    32 
    33 il void insert(RG int from,RG int to,RG int cap,RG int cost){ g[++num]=(edge){head[from],to,0,cap,cost},head[from]=num; }
    34 
    35 il int bfs(RG int S,RG int T){
    36     for (RG int i=1;i<=n+3;++i) dis[i]=inf;
    37     Q.push(S),flow[S]=inf,dis[S]=0;
    38     while (!Q.empty()){
    39     RG int x=Q.front(),v; Q.pop();
    40     for (RG int i=head[x];i;i=g[i].nt){
    41         v=g[i].to;
    42         if (dis[v]>dis[x]+g[i].cost && g[i].cap>g[i].flow){
    43         flow[v]=min(flow[x],g[i].cap-g[i].flow);
    44         dis[v]=dis[x]+g[i].cost; fa[v]=x,p[v]=i,Q.push(v);
    45         }
    46     }
    47     }
    48     if (dis[T]==inf) return 0; cost+=flow[T]*dis[T];
    49     for (RG int x=T;x!=S;x=fa[x]) g[p[x]].flow+=flow[T],g[p[x]^1].flow-=flow[T];
    50     return 1;
    51 }
    52 
    53 il int mcmf(RG int S,RG int T){ cost=0; while (bfs(S,T)); return cost; }
    54 
    55 il void work(){
    56     n=gi(),m=gi(); S=n+2,T=n+3; insert(S,1,inf,0),insert(1,S,0,0);
    57     for (RG int i=1;i<=n;++i) a[i]=gi(),insert(i,i+1,inf-a[i],0),insert(i+1,i,0,0);
    58     for (RG int i=1;i<=m;++i){
    59     RG int s=gi(),t=gi(),c=gi();
    60     insert(s,t+1,inf,c),insert(t+1,s,0,-c);
    61     }
    62     insert(n+1,T,inf,0),insert(T,n+1,0,0);
    63     printf("%d
    ",mcmf(S,T)); return;
    64 }
    65 
    66 int main(){
    67     File("volunteer");
    68     work();
    69     return 0;
    70 }

    这题用线性规划,设第i种志愿者为xi,则根据样例,必须满足:

    min{2x1+5x2+2x3},x1>=2,x1+x2>=3,x2+x3>=4,x1,x2,x3>=0。

    但是这不是线性规划的标准型,没有基本可行解,所以我们可以考虑对偶变换。

    给定一个最大化目标的线性规划,我们应该描述如何形式化一个对偶线性规划,其中目标是最小化,而且最优值与初始线性规划的最优值相同。当表示对偶性规划时,我们称初始的线性规划为原始线性规划。为了构造对偶问题,我们将最大化改为最小化,交换右边系数与目标系数,并且将小于等于改为大于等于。原始问题的m个越是,每一个在对偶问题中都有一个对应的变量yi,对偶问题的n个约束,每一个在原始问题中都有一个对应的变量xj。

    ——算法导论

    然后我们就可以把上面的线性规划变成:

    max{2x1+3x2+4x3},x1+x2<=2,x2+x3<=5,x3<=2,x1,x2,x3>=0。

    这样,我们就可以直接套用模板了。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <complex>
     5 #include <cstring>
     6 #include <cstdlib>
     7 #include <cstdio>
     8 #include <vector>
     9 #include <cmath>
    10 #include <queue>
    11 #include <stack>
    12 #include <map>
    13 #include <set>
    14 #define eps (1e-12)
    15 #define inf (1e15)
    16 #define il inline
    17 #define RG register
    18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    19 
    20 using namespace std;
    21 
    22 double a[10010][1010],ans;
    23 int b[1010],n,m;
    24 
    25 il int gi(){
    26     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    27     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
    28 }
    29 
    30 il void pivot(RG int l,RG int e){
    31     RG double k=a[l][e]; a[l][e]=1;
    32     for (RG int i=0;i<=n;++i) a[l][i]/=k; RG int len=0;
    33     for (RG int i=0;i<=n;++i) if (fabs(a[l][i])>eps) b[++len]=i;
    34     for (RG int i=0;i<=m;++i)
    35     if (i!=l && fabs(a[i][e])>eps){
    36         k=a[i][e],a[i][e]=0;
    37         for (RG int j=1;j<=len;++j) a[i][b[j]]-=k*a[l][b[j]];
    38     }
    39     return;
    40 }
    41 
    42 il double simplex(){
    43     while (1){
    44     RG int l,e; for (e=1;e<=n;++e) if (a[0][e]>eps) break;
    45     if (e==n+1) return -a[0][0]; RG double tmp=inf;
    46     for (RG int i=1;i<=m;++i)
    47         if (a[i][e]>eps && a[i][0]/a[i][e]<tmp) tmp=a[i][0]/a[i][e],l=i;
    48     if (tmp==inf) return inf; pivot(l,e);
    49     }
    50 }
    51 
    52 il void work(){
    53     n=gi(),m=gi(); RG int s,t,d;
    54     for (RG int i=1;i<=n;++i) scanf("%lf",&a[0][i]);
    55     for (RG int i=1;i<=m;++i){
    56     s=gi(),t=gi(),d=gi(),a[i][0]=d;
    57     for (RG int j=s;j<=t;++j) a[i][j]=1;
    58     }
    59     printf("%d",(int)(simplex()+0.5)); return;
    60 }
    61 
    62 int main(){
    63     File("volunteer+");
    64     work();
    65     return 0;
    66 }
  • 相关阅读:
    JS的运行机制
    Vue路由
    javascript的逼格
    Vue开发中遇到的问题及解决方案
    模块模式
    2019年终总结
    http知识总结
    小议函数的节流和防抖
    nodejs初探一二
    Object是个什么鬼
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6428248.html
Copyright © 2020-2023  润新知