单纯形求解线性规划(BZOJ1061)

推荐一篇论文:http://wenku.baidu.com/view/ce5784754a7302768f99391d

我们设xi为第i个志愿者的招募次数,以样例为例,则不难列出如下的线性规划方程:

min{2x1+5x2+2x3}

x1+0+0>=2

x1+x2+0>=3

0+x2+x3>=4

那么,根据论文,这个方程等价于:

max{2x1+3x2+4x3}

x1+x2+0<=2

0+x2+x3<=5

0+0+x3<=2

我们发现,这是一个线性规划方程的基本形式,基本解为{0,0,0}

然后套模板就可以了。

#include <cstdio>

const int N=1005,M=10005;
int n,m,x,y,p,id;
double ans,c[N],b[M],a[M][N];

void pvt(int id,int p) {
    a[id][p]=1/a[id][p],b[id]*=a[id][p];
    for(int i=1;i<=n;i++) if(i^p) a[id][i]*=a[id][p];
    for(int i=1;i<=m;i++) if((i^id)&&a[i][p]) {
        for(int j=1;j<=n;j++) if(j^p) a[i][j]-=a[i][p]*a[id][j];
        b[i]-=a[i][p]*b[id],a[i][p]*=-a[id][p];
    }
    for(int i=1;i<=n;i++) if(i^p) c[i]-=c[p]*a[id][i];
    ans+=c[p]*b[id],c[p]*=-a[id][p];
}
double sol() {
    while(1) {
        for(p=1;p<=n;p++) if(c[p]>0) break;
        if(p==n+1) return ans;
        double fz=0x3f3f3f3f;
        for(int i=1;i<=m;i++) if(a[i][p]>0&&b[i]/a[i][p]<fz) fz=b[i]/a[i][p],id=i;
        if(fz==0x3f3f3f3f) return fz;
        pvt(id,p);
    }
}

int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%lf",&c[i]);
    for(int i=1;i<=m;i++) {
        scanf("%d%d%lf",&x,&y,&b[i]);
        for(int j=x;j<=y;j++) a[i][j]=1;
    }
    printf("%.0f",sol());
    return 0;
}
posted @ 2017-01-12 08:21  Monster_Yi  阅读(1247)  评论(0编辑  收藏  举报