【模板】线性规划题解

P13337 【模板】线性规划

题目描述

本题中你需要求解一个标准型线性规划:

nnn 个实数变量 x1,x2,…,xnx_1,x_2,\dots,x_nx1,x2,,xnmmm 条约束,其中第 iii 条约束形如 ∑j=1nai,jxj≤bi\sum_{j=1}^n a_{i,j}x_j \le b_ij=1nai,jxjbi

此外这 nnn 个变量需要满足非负性限制,即 xj≥0x_j\ge 0xj0

在满足上述所有条件的情况下,你需要指定每个变量 xjx_jxj 的取值,使得目标函数 F=∑j=1ncjxjF=\sum_{j=1}^n c_j x_jF=j=1ncjxj 的值最大。

保证数据随机。

输入格式

第一行两个正整数 n,mn,mn,m

第二行有 nnn 个整数 c1,c2,⋯ ,cnc_1,c_2,\cdots,c_nc1,c2,,cn,整数间均用一个空格分隔。

接下来 mmm 行,每行代表一条约束,其中第 iii 行有 n+1n+1n+1 个整数 ai,1,ai,2,⋯ ,ai,n,bia_{i,1},a_{i,2},\cdots,a_{i,n}, b_iai,1,ai,2,,ai,n,bi,整数间均用一个空格分隔。

输出格式

如果不存在满足所有约束的解,仅输出一行 Infeasible

如果对于任意的 MMM,都存在一组解使得目标函数的值大于 MMM,仅输出一行 Unbounded

否则,第一行输出一个实数,表示目标函数的最大值 FFF。当第一行与标准答案的相对误差或绝对误差不超过 10−610^{-6}106,你的答案被判为正确。

第二行输出用空格隔开的 nnn 个非负实数,表示此时 x1,x2,…,xnx_1,x_2,\dots,x_nx1,x2,,xn 的取值,如有多组方案请任意输出其中一个。

判断第二行是否合法时,我们首先检验 FFF∑j=1ncjxj\sum_{j=1}^n c_j x_jj=1ncjxj 的相对误差或绝对误差不超过 10−610^{-6}106,再对于所有 iii,检验 ∑j=1nai,jxj≤bi\sum_{j=1}^n a_{i,j}x_j\le b_ij=1nai,jxjbi∑j=1nai,jxj\sum_{j=1}^n a_{i,j}x_jj=1nai,jxjbib_ibi 的相对误差或绝对误差不超过 10−610^{-6}106。若均满足,则判为正确。

如果出现 InfeasibleUnbounded 时,不需要输出第二行。

输入输出样例 #1

输入 #1

2 2
1 1
2 1 6
-1 2 3

输出 #1

4.2
1.8 2.4

输入输出样例 #2

输入 #2

2 2
1 -1
1 1 4
-1 -2 -2

输出 #2

4.0
4.0 0.0

输入输出样例 #3

输入 #3

3 3
0 0 1
-2 1 0 -4
1 1 0 4
1 -2 0 -4

输出 #3

Infeasible

输入输出样例 #4

输入 #4

2 1
0 1
1 0 1

输出 #4

Unbounded

说明/提示

数据范围

对于所有数据,1≤n,m≤1001\leq n,m \leq 1001n,m1000≤∣ai,j∣,∣bi∣,∣cj∣≤1000 \leq |a_{i,j}|,|b_i|,|c_j|\leq 1000ai,j,bi,cj100。保证数据随机。

子任务编号$n,m\le $特殊性质分值
1101010202020
2202020202020
3505050bi≥0b_i\ge 0bi0101010
4505050202020
5100100100303030

思路

单纯型法!

代码见下

#include<bits/stdc++.h>
using namespace std;
long long n,m,b[5005],nn[5005],at;
long double a[5005][5005],xc[5005];
constexpr long double ep=1e-15l;
void abc(long long x,long long y){
    swap(nn[x],b[y]);
    long double v=-1.00/a[x][y];
    for(int j=0;j<=m+1;j++){
        if(j==y){
            a[x][j]=-v;
        }
        else{
            a[x][j]=v*a[x][j];
        }
    }
    for(int i=0;i<=n;i++){
        if(i!=x){
            v=a[i][y];
            a[i][y]=0;
            for(int j=0;j<=m+1;j++){
                a[i][j]+=v*a[x][j];
            }
        }
    }
    return ;
}
long long bcd(){
    long long nc=0;
    for(int j=0;j<=m-1;j++){
        if(a[n][j]<-ep){
            for(int i=0;i<=n;i++){
                a[i][m+1]+=a[i][j];
            }
            b[j]=~b[j];
            nc++;
        }
    }
    while(nc!=0){
        long long x=-1;
        long double mi=-ep;
        for(int i=0;i<=n-1;i++){
            if(a[i][m+1]<mi){
                x=i;
                mi=a[i][m+1];
            }
        }
        if(x==-1){
            return 0;
        }
        long long y=-1;
        mi=INFINITY;
        for(int j=0;j<=m-1;j++){
            if((b[j]<=-1&&a[x][j]<-ep)||(b[j]>=0&&a[x][j]>ep)){
                long double tm=a[n][j]/a[x][j];
                if(b[j]<=-1){
                    tm-=ep;
                }
                else{
                    tm+=ep;
                }
                if(tm<mi){
                    y=j;
                    mi=tm;
                }
            }
        }
        if(b[y]<=-1){
            nc--;
            b[y]=~b[y];
            abc(x,y);
            a[x][m+1]+=1.00;
        }
        else{
            abc(x,y);
        }
    }
    return 1;
}
long long cde(){
    // for(int i=0;i<=n;i++){
    //     for(int j=0;j<=m+1;j++){
    //         cout<<a[i][j]<<" ";
    //     }
    //     cout<<endl;
    // }
    // for(int i=0;i<=m;i++){
    //     cout<<b[i]<<" ";
    // }
    // cout<<endl;
    // for(int j=0;j<=n;j++){
    //     cout<<nn[j]<<" ";
    // }
    // cout<<endl;
    while(1){
        long long x=-1;
        long double mi=-ep;
        for(int i=0;i<=n-1;i++){
            if(a[i][m]<mi){
                x=i;
                mi=a[i][m];
            }
        }        
        if(x==-1){
            break;
        }
        long long y=-1;
        mi=INFINITY;
        for(int j=0;j<=m-1;j++){
            if(a[x][j]>ep){
                if(a[n][j]/a[x][j]<mi){
                    y=j;
                    mi=a[n][j]/a[x][j];                    
                }
            }
        }
        if(y==-1){
            return 0;
        }
        abc(x,y);
    }    
    return 1;
}
long long def(){
    for(int i=0;i<=m-1;i++){
        b[i]=n+i;
    }
    for(int i=0;i<=n-1;i++){
        nn[i]=i;
    }
    if(bcd()==1){
        if(cde()==1){
            return 0;
        }
        else{
            return 1;
        }
    }
    else{
        return -1;
    }
}
int main(){
    cin>>n>>m;
    for(int i=0;i<=n-1;i++){
        cin>>a[i][m];
        a[i][m]=-a[i][m];
    }
    for(int j=0;j<=m-1;j++){
        for(int i=0;i<=n;i++){
            cin>>a[i][j];
        }
    }
    at=def();
    // for(int i=0;i<=m;i++){
    //    cout<<b[i]<<" ";
    // }
    // cout<<endl;
    if(at==-1){
        cout<<"Infeasible"<<endl;
    }
    else if(at==1){
        cout<<"Unbounded"<<endl;
    }
    else{
        printf("%.10llf\n",a[n][m]);
        // for(int i=0;i<=n;i++){
        //     for(int j=0;j<=m+1;j++){
        //         cout<<a[i][j]<<" ";
        //     }
        //     cout<<endl;
        // }
        for(int j=0;j<=m-1;j++){
            if(b[j]<=n-1){
                xc[b[j]]=a[n][j];
                //cout<<b[j]<<endl;
            }
        }
        for(int i=0;i<=n-1;i++){
            printf("%.10llf ",xc[i]);
        }
        cout<<endl;
    }
	return 0;
}
posted @ 2026-01-14 21:05  bz02_2023f2  阅读(4)  评论(0)    收藏  举报  来源