zoukankan      html  css  js  c++  java
  • bzoj3550: [ONTAK2010]Vacation&&bzoj3112: [Zjoi2013]防守战线

    学了下单纯形法解线性规划

    看起来好像并不是特别难,第二个code有注释。我还有...*=-....这个不是特别懂

    第一个是正常的,第二个是解对偶问题的

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const double eps=1e-7;
    
    int n,m; double sum;
    double a[1100][1100],b[1100],c[1100];
    void pivot(int o,int e)
    {
        b[o]/=a[o][e];
        for(int i=1;i<=n;i++)
            if(i!=e)a[o][i]/=a[o][e];
        a[o][e]=1/a[o][e];
        
        for(int i=1;i<=m;i++)
            if(i!=o&&fabs(a[i][e])>eps)
            {
                b[i]-=b[o]*a[i][e];
                for(int j=1;j<=n;j++)
                    if(j!=e)a[i][j]-=a[o][j]*a[i][e];
                a[i][e]*=-a[o][e];
            }
            
        sum+=c[e]*b[o];
        for(int i=1;i<=n;i++)
            if(i!=e)c[i]-=a[o][i]*c[e];
        c[e]*=-a[o][e];
    }
    void simplex()
    {
        int e,o; double d;
        while(1)
        {
            d=0;
            for(int i=1;i<=n;i++)
                if(c[i]>d)d=c[i],e=i;
            if(d==0)return ;
            
            d=(1<<30);
            for(int i=1;i<=m;i++)
                if(a[i][e]>eps&&d>b[i]/a[i][e])
                    d=b[i]/a[i][e],o=i;
            if(d==(1<<30)){sum=(1<<30);return ;}
            
            pivot(o,e);
        }
    }
    int main()
    {
        int K;
        scanf("%d%d",&n,&K);m=2*n+1;n*=3;
        for(int i=1;i<=n;i++)scanf("%lf",&c[i]);
        for(int i=1;i<=m;i++)
        {
            b[i]=K;
            for(int j=1;j<=n/3;j++)a[i][i+j-1]++;
        }
        for(int i=1;i<=n;i++)
            b[m+i]=1,a[m+i][i]++;
        m+=n;
        sum=0;simplex();
        printf("%.0lf
    ",sum);
        return 0;
    }
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const double eps=1e-7;
    
    int n,m; double sum;
    double a[1100][11000],b[11000],c[1100];
    //解的过程中,由于基变量xi=ci,所以c也代表放在当前约束的基变量取值
    
    void pivot(int o,int e)//把作为第o个约束的基变量用e替换 
    {
        c[o]/=a[o][e];//没有替换之前,e的取值被当前限制,是c[o]/a[i][e],先令x=c
        for(int i=1;i<=m;i++)//把e的系数消掉,其实常数项c也是同理的 
            if(i!=e)a[o][i]/=a[o][e];
        a[o][e]=1/a[o][e];//难点!取倒数相当于保留了自己的常数项,而除以了上一个的常数项,这样下面就可以直接消除上一个的影响了 
        
        for(int i=1;i<=n;i++)
            if(i!=o&&fabs(a[i][e])>eps)//对于其它的约束条件,把离基的变量用进基的变量替代 
            {
                c[i]-=c[o]*a[i][e];
                for(int j=1;j<=m;j++) 
                    if(j!=e)a[i][j]-=a[o][j]*a[i][e];
                a[i][e]*=-a[o][e];
            }
        
        sum+=b[e]*c[o];//系数乘以值 
        for(int i=1;i<=m;i++)//对于第i个变量当前已经用了b[e]*a[o][i]来贡献答案了 
            if(i!=e)b[i]-=a[o][i]*b[e];
        b[e]*=-a[o][e];
    }
    void simplex()
    {
        int e,o; double d; 
        while(1)
        {
            d=0;//找进基的变量
            for(int i=1;i<=m;i++)//基变量的b一定<=0,在非基变量中找一个对答案贡献最大(系数最大)的进基
                if(b[i]>d)d=b[i],e=i;
            if(d==0)return ;
            
            d=(1<<30);//找离基的变量,进基变量系数的非负比要最小 
            for(int i=1;i<=n;i++)//找对e的最小约束(即用此新角点截距最小,也就是当前e的取值被这个约束条件约束)离基 
                if(a[i][e]>eps&&d>c[i]/a[i][e])
                    d=c[i]/a[i][e],o=i;
            if(d==(1<<30)){sum=(1<<30);return ;}
            
            pivot(o,e);
        }
    }
    
    int main()
    {
        int l,r;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%lf",&c[i]);
        memset(a,0,sizeof(a));
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%lf",&l,&r,&b[i]);
            for(int j=l;j<=r;j++)a[j][i]++;
        }
        simplex();
        printf("%.0lf
    ",sum);
        
        return 0;
    }

    ---恢复内容结束---

  • 相关阅读:
    在X++中使用IoC/DI模式应对不断变化的客户需求
    Predicate<T>与Func<T, bool>泛型委托
    Windows Live Writer插件:在WLW中插入语法高亮代码
    学习C#和.NET的资源
    C#中事件的动态调用
    2008年全国软件工程大会论文集
    C#基础:接口(二)
    【转载】"变化"、"复用"、"抽象"、"稳定" 影响着软件设计模式,架构,开发方法
    【领域驱动设计】.NET实践:实体、值对象和数据传输对象
    RSS订阅之基本使用
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10203519.html
Copyright © 2011-2022 走看看