zoukankan      html  css  js  c++  java
  • 线性规划

    单纯形

    求解线性规划最优解问题(全部转化成约束条件<=(非负条件可以是>=),并且求最大值问题)

    bzoj1061 志愿者招募

    题目大意:给定n天,每天需要志愿者ai人;m类志愿者,从si~ti天工作,每人要ci元。求最小费用。

    思路:根据题意可以列出目标函数是min sigma(i=1~m)cixi,约束条件是 sigma(i=1~m)Aijxi>=aj(j=1~n)(Aij表示这一天志愿者能否工作),xi>=0。这个问题如果*-1转化的话,可能要求解辅助约束。所以可以用对偶问题来解决,目标函数是max sigma(i=1~n)aiyi,约束条件是sigma(i=1~n)Aijyi<=cj(j=1~m),yi>=0,然后就可以求解了。pivot是转轴过程,相当于把xl约束中的xe提到左边,同时代入其他的约束和目标函数。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 1005
    #define M 10005
    #define LD double
    #define eps 1e-9
    #define inf 1e10
    using namespace std;
    LD a[M][N],b[M],c[M];
    int n,m;LD v;
    int cmp(LD x,LD y){
        if (x-y>eps) return 1;
        if (y-x>eps) return -1;
        return 0;}
    void pivot(int l,int e){
        int i,j;
        b[l]/=a[l][e];
        for (i=1;i<=n;++i)
          if (i!=e) a[l][i]/=a[l][e];
        a[l][e]=1./a[l][e];
        for (i=1;i<=m;++i)
            if (i!=l&&cmp(a[i][e],eps)!=0){
                b[i]-=a[i][e]*b[l];
                for (j=1;j<=n;++j)
                    if (j!=e) a[i][j]-=a[i][e]*a[l][j];
                a[i][e]=-a[i][e]*a[l][e];}
        v+=c[e]*b[l];
        for (i=1;i<=n;++i)
          if (i!=e) c[i]-=a[l][i]*c[e];
        c[e]=-a[l][e]*c[e];}
    LD simplex(){
        int i,j,l,e;LD del;
        while(true){
            for (i=1;i<=n;++i) if (c[i]>eps) break;
            if (i>n) return v;
            del=inf;e=i;
            for (i=1;i<=m;++i)
                if (a[i][e]>eps&&del>b[i]/a[i][e]){
                    del=b[i]/a[i][e];l=i;
                }
            if (cmp(del,inf)==0) return inf;
            else pivot(l,e);
        }}
    int main(){
        int i,j,s,t,cc;scanf("%d%d",&n,&m);
        for (i=1;i<=n;++i) scanf("%lf",&c[i]);
        for (i=1;i<=m;++i){
            scanf("%d%d%lf",&s,&t,&b[i]);
            for (j=s;j<=t;++j) a[i][j]=1.;
        }printf("%.0f
    ",simplex());
    }
    View Code

    bzoj3112 防守战线

    题目大意:给定n个位置和每个位置建一个防具的花费,每个位置可以建无穷多个防具,m个要求(s~t位置的防具个数不少于d个),求最小费用。

    思路:和上面的一样,只是b、c、n、m互换了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 1005
    #define M 10005
    #define inf 1e10
    #define eps 1e-9
    #define LD double
    using namespace std;
    LD a[N][M]={0.},b[N],c[M],v=0.;
    int n,m;
    int cmp(LD x,LD y){
        if (x-y>eps) return 1;
        if (y-x>eps) return -1;
        return 0;}
    void pivot(int l,int e){
        int i,j;
        b[l]/=a[l][e];
        for (i=1;i<=m;++i)
          if (i!=e) a[l][i]/=a[l][e];
        a[l][e]=1./a[l][e];
        for (i=1;i<=n;++i)
            if (i!=l&&cmp(a[i][e],0.)!=0){
                b[i]-=b[l]*a[i][e];
                for (j=1;j<=m;++j)
                    if (j!=e) a[i][j]-=a[l][j]*a[i][e];
                a[i][e]=-a[i][e]*a[l][e];}
        v+=c[e]*b[l];
        for (i=1;i<=m;++i)
          if (i!=e) c[i]-=c[e]*a[l][i];
        c[e]=-c[e]*a[l][e];}
    LD simplex(){
        int l,e,i,j;LD del;
        while(true){
            for (i=1;i<=m;++i) if (c[i]>eps) break;
            if ((e=i)>m) return v;
            del=inf;
            for (i=1;i<=n;++i)
                if (a[i][e]>eps&&cmp(del,b[i]/a[i][e])>0){
                    del=b[i]/a[i][e];l=i;}
            if (cmp(del,inf)==0) return inf;
            else pivot(l,e);
        }}
    int main(){
        int i,j,s,t;scanf("%d%d",&n,&m);
        for (i=1;i<=n;++i) scanf("%lf",&b[i]);
        for (i=1;i<=m;++i){
            scanf("%d%d%lf",&s,&t,&c[i]);
            for (j=s;j<=t;++j) a[j][i]=1.;
        }printf("%.0f
    ",simplex());
    }
    View Code

    拉格朗日乘数法

    bzoj2876 骑行川藏

    题目大意:已知n段路程的距离si、参数ki、风速vi和初始能量Eu,给n段路程定一个速度,每一段的能量为Ei=ki*(vi-vi')^2*si,要求总能量<=Eu,求最短时间。

    思路:相当于sigma(i=1~n)Ei<=Eu,min(si/xi)。对于这样的约束系统,可以用拉格朗日乘数法,得到偏导数方程组2*λ*ki*vi^2*(vi-vi')=1(vi>=vi'),其中E随vi递增,E随λ递减,可以二分λ,找到sigma(i=1~n)Ei=Eu的λ,通过二分解出每个vi,这道题目中因为只有一个λ,所以可以算出唯一解。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define inf 1e9
    #define eps 1e-14
    #define LD double
    #define N 10005
    using namespace std;
    int cmp(LD x,LD y){
        if (x-y>eps) return 1;
        if (y-x>eps) return -1;
        return 0;}
    int n;
    LD eu,si[N],ki[N],vv[N],vi[N];
    LD getf(LD x,int i){return x*x*(x-vv[i]);}
    LD sqr(LD x){return x*x;}
    LD judge(LD x){
        int i;LD aa,l,r,mid,sm=0.;
        for (i=1;i<=n;++i){
            aa=1./2./x/ki[i];
            l=max(0.,vv[i]);r=inf;
            while(r-l>eps){
                mid=(l+r)/2.;
                if (cmp(getf(mid,i),aa)>=0) r=mid;
                else l=mid;
            }vi[i]=l;
            sm+=ki[i]*sqr(vi[i]-vv[i])*si[i];
        }return sm;}
    int main(){
        int i;LD l,r,mid,ans=0.;scanf("%d%lf",&n,&eu);
        for (i=1;i<=n;++i) scanf("%lf%lf%lf",&si[i],&ki[i],&vv[i]);
        l=0.;r=inf;
        while(r-l>eps){
            mid=(l+r)/2.;
            if (cmp(judge(mid),eu)>=0) l=mid;
            else r=mid;
        }for (i=1;i<=n;++i) ans+=si[i]/vi[i];
        printf("%.8f
    ",ans);
    }
    View Code
  • 相关阅读:
    为什么说 Mybatis 是半自动 ORM 映射工具?它与全自动的区别在哪里?
    http的响应码200,404,302,500表示的含义分别是?
    说一下 session 的工作原理?
    session 和 cookie 有什么区别?
    什么是 MyBatis?
    SpringMVC 工作原理?
    报表数据填报中的合法性校验
    报表数据填报中的自动计算
    如何用报表工具实现树状层级结构的填报表
    在报表中录入数据时如何实现行列转换
  • 原文地址:https://www.cnblogs.com/Rivendell/p/5119068.html
Copyright © 2011-2022 走看看