zoukankan      html  css  js  c++  java
  • BZOJ 3112: [Zjoi2013]防守战线 [单纯形法]

    题目描述

    战线可以看作一个长度为n 的序列,现在需要在这个序列上建塔来防守敌兵,在序列第i 号位置上建一座塔有Ci 的花费,且一个位置可以建任意多的塔,费用累加计算。有m 个区间[L1, R1], [L2, R2], …, [Lm, Rm],在第i 个区间的范围内要建至少Di 座塔。求最少花费。

    输入输出格式

    输入格式:

    第一行为两个数n, m。

    接下来一行,有n 个数,描述C 数组。

    接下来m 行,每行三个数Li,Ri,Di,描述一个区间。

    输出格式:

    仅包含一行,一个数,为最少花费。

    输入输出样例

    输入样例#1:
    5 3
    1 5 6 3 4
    2 3 1
    1 5 4
    3 5 2
    输出样例#1:
    11

    说明

    【样例说明】

    位置1 建2 个塔,位置3 建一个塔,位置4 建一个塔。花费1*2+6+3=11。

    【数据规模】

    对于20%的数据,n≤20,m≤20。

    对于50%的数据(包括上部分的数据),Di 全部为1。

    对于70%的数据(包括上部分的数据),n≤100,m≤1000。

    对于100%的数据,n≤1000,m≤10000,1≤Li≤Ri≤n,其余数据均≤10000。


    [2016-12-7] 

    和08志愿者招募很像

    设X为每个位置建塔数量的向量

    最小化 CX

    满足约束 第i个约束为x[l[i]]+x[l[i]+1]+...+x[r[i]]>=d[i]

    即AX>=D

    A[i][j]为1表示第i个约束中j在[l[i],r[i]]里,可以贡献到和中

    对偶之后,就成了

    最大化 DX

    满足约束 AT X<=C

    注意这时候这时候是n个约束,m个变量

    [2017-03-11]

    重写一遍

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=1005,M=1e4+5;
    const double INF=1e15,eps=1e-8;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int n,m;
    double a[N][M];
    int q[M];
    void Pivot(int l,int e){
        double t=a[l][e];a[l][e]=1;
        for(int j=0;j<=n;j++) a[l][j]/=t;
        int p=0;
        for(int j=0;j<=n;j++) if(abs(a[l][j])>eps) q[++p]=j;
        for(int i=0;i<=m;i++) if(i!=l && abs(a[i][e])>eps){
            double t=a[i][e];a[i][e]=0;
            for(int j=1;j<=p;j++) a[i][q[j]]-=t*a[l][q[j]];
        }
    }
    void simplex(){
        while(true){
            int l=0,e=0; double mn=INF;
            for(int j=1;j<=n;j++) if(a[0][j]>eps) {e=j;break;}
            if(!e) return;
            for(int i=1;i<=m;i++) 
                if(a[i][e]>eps && a[i][0]/a[i][e]<mn) {mn=a[i][0]/a[i][e];l=i;}
            if(!l) return;//unbounded
            Pivot(l,e);
        }
    }
    int main(){
        freopen("in","r",stdin);
        n=read();m=read();
        swap(n,m);
        for(int i=1;i<=m;i++) a[i][0]=read();
        for(int j=1;j<=n;j++){
            int l=read(),r=read();
            for(int i=l;i<=r;i++) a[i][j]=1;
            a[0][j]=read();
        }
        simplex();
        printf("%d",int(-a[0][0]+0.5));
    }
  • 相关阅读:
    PHP 生成二维码底部拼接文字和中间拼接logo
    牛客练习赛85
    Codeforces Round #729 (Div. 2)
    Codeforces Round #727 (Div. 2)
    AtCoder Beginner Contest 206(Sponsored by Panasonic)
    Codeforces Round #726 (Div. 2)
    Codeforces Round #722 (Div. 2)
    Codeforces Round #721 (Div. 2)
    AtCoder Regular Contest 118
    牛客练习赛82
  • 原文地址:https://www.cnblogs.com/candy99/p/6189525.html
Copyright © 2011-2022 走看看