2014-team3/code/lp

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

{{{
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;

typedef double dbl;
const dbl inf = 1e99,eps = 1e-8;
struct LP{
    static const size_t N=20,M=20,L=N+M*2,faux=~0; 
    dbl A[M][L],b[M],c[N+M],c1[L],x[N],d[L],zm;
    size_t bs[M],n,m,l;
#define go(i,n) for(i=0;i<n;++i) 
    dbl simplex(dbl *c){
        for(size_t j,k,i,o;;bs[o]=i){
            dbl dmax=0,u=inf,t;
            i=o=-1;
            go(k,l){
                d[k]=c[k];
                go(j,m)d[k]-=c[bs[j]]*A[j][k];
                if(d[k]>dmax+eps){dmax=d[k];i=k;}
            }
            if(!~i){
                zm=0;fill(x,x+n,0);
                go(j,m)if(bs[j]<n)
                    zm+=c[bs[j]]*(x[bs[j]]=b[j]);
                return zm;
            }
            go(j,m)if(A[j][i]>eps&&b[j]/A[j][i]+eps<u)
                u=b[o=j]/A[j][i];
            if(!~o)throw "unbounded!";
            b[o]*=t=1/A[o][i];
            go(k,l)A[o][k]*=t;
            go(j,m)if(j!=o&&fabs(A[j][i])>eps){
                t=-A[j][i];b[j]+=t*b[o];
                go(k,l)A[j][k]+=t*A[o][k];
            }
        }
    }
    void init(int _n){
        memset(A,0,sizeof(A));
        memset(b,0,sizeof(b));
        memset(c,0,sizeof(c));
        l=n=_n;m=0;
    }
    void add_contraint(dbl* a,dbl _b,bool eq=false){
        copy(a,a+n,A[m]);b[m]=_b;
        if(eq||_b<0)bs[m]=faux;
        else A[m][bs[m]=l++]=1;
        m++;
    }
    dbl solve(){
        size_t ol=l,j,k;
        go(j,m)if(bs[j]==faux)A[j][bs[j]=l++]=1;
        if(ol!=l){
            go(k,l)c1[k]=k<ol?0:-1;
            if(simplex(c1)<-eps)throw "infeasible";
            l=ol;
        }
        return simplex(c);
    }
};
LP a;
int main(){
        int n,m,i,j;
        while(cin >> n >> m){
                a.init(n);
                dbl t[100];
                go(i,n)cin >> a.c[i];
                go(j,m){
                        go(i,n)cin >> t[i];
                        dbl b;cin >> b;
                        a.add_contraint(t,b);
                }
                long long ans = a.solve()*m+0.9999999;
                cout << "Nasa can spend "<< ans<<" taka."<< endl;
        }
}
}}}
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef double dbl;
const dbl inf = 1e99,eps = 1e-8;
struct LP{
    static const size_t N=20,M=20,L=N+M*2,faux=~0; 
    dbl A[M][L],b[M],c[N+M],c1[L],x[N],d[L],zm;
    size_t bs[M],n,m,l;
#define go(i,n) for(i=0;i<n;++i) 
    dbl simplex(dbl *c){
        for(size_t j,k,i,o;;bs[o]=i){
            dbl dmax=0,u=inf,t;
            i=o=-1;
            go(k,l){
                d[k]=c[k];
                go(j,m)d[k]-=c[bs[j]]*A[j][k];
                if(d[k]>dmax+eps){dmax=d[k];i=k;}
            }
            if(!~i){
                zm=0;fill(x,x+n,0);
                go(j,m)if(bs[j]<n)
                    zm+=c[bs[j]]*(x[bs[j]]=b[j]);
                return zm;
            }
            go(j,m)if(A[j][i]>eps&&b[j]/A[j][i]+eps<u)
                u=b[o=j]/A[j][i];
            if(!~o)throw "unbounded!";
            b[o]*=t=1/A[o][i];
            go(k,l)A[o][k]*=t;
            go(j,m)if(j!=o&&fabs(A[j][i])>eps){
                t=-A[j][i];b[j]+=t*b[o];
                go(k,l)A[j][k]+=t*A[o][k];
            }
        }
    }
    void init(int _n){
        memset(A,0,sizeof(A));
        memset(b,0,sizeof(b));
        memset(c,0,sizeof(c));
        l=n=_n;m=0;
    }
    void add_contraint(dbl* a,dbl _b,bool eq=false){
        copy(a,a+n,A[m]);b[m]=_b;
        if(eq||_b<0)bs[m]=faux;
        else A[m][bs[m]=l++]=1;
        m++;
    }
    dbl solve(){
        size_t ol=l,j,k;
        go(j,m)if(bs[j]==faux)A[j][bs[j]=l++]=1;
        if(ol!=l){
            go(k,l)c1[k]=k<ol?0:-1;
            if(simplex(c1)<-eps)throw "infeasible";
            l=ol;
        }
        return simplex(c);
    }
};
LP a;
int main(){
        int n,m,i,j;
        while(cin >> n >> m){
                a.init(n);
                dbl t[100];
                go(i,n)cin >> a.c[i];
                go(j,m){
                        go(i,n)cin >> t[i];
                        dbl b;cin >> b;
                        a.add_contraint(t,b);
                }
                long long ans = a.solve()*m+0.9999999;
                cout << "Nasa can spend "<< ans<<" taka."<< endl;
        }
}