【模板】线性规划题解
P13337 【模板】线性规划
题目描述
本题中你需要求解一个标准型线性规划:
有 nnn 个实数变量 x1,x2,…,xnx_1,x_2,\dots,x_nx1,x2,…,xn 和 mmm 条约束,其中第 iii 条约束形如 ∑j=1nai,jxj≤bi\sum_{j=1}^n a_{i,j}x_j \le b_i∑j=1nai,jxj≤bi。
此外这 nnn 个变量需要满足非负性限制,即 xj≥0x_j\ge 0xj≥0。
在满足上述所有条件的情况下,你需要指定每个变量 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}10−6,你的答案被判为正确。
第二行输出用空格隔开的 nnn 个非负实数,表示此时 x1,x2,…,xnx_1,x_2,\dots,x_nx1,x2,…,xn 的取值,如有多组方案请任意输出其中一个。
判断第二行是否合法时,我们首先检验 FFF 与 ∑j=1ncjxj\sum_{j=1}^n c_j x_j∑j=1ncjxj 的相对误差或绝对误差不超过 10−610^{-6}10−6,再对于所有 iii,检验 ∑j=1nai,jxj≤bi\sum_{j=1}^n a_{i,j}x_j\le b_i∑j=1nai,jxj≤bi 或 ∑j=1nai,jxj\sum_{j=1}^n a_{i,j}x_j∑j=1nai,jxj 与 bib_ibi 的相对误差或绝对误差不超过 10−610^{-6}10−6。若均满足,则判为正确。
如果出现 Infeasible 或 Unbounded 时,不需要输出第二行。
输入输出样例 #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 1001≤n,m≤100,0≤∣ai,j∣,∣bi∣,∣cj∣≤1000 \leq |a_{i,j}|,|b_i|,|c_j|\leq 1000≤∣ai,j∣,∣bi∣,∣cj∣≤100。保证数据随机。
| 子任务编号 | $n,m\le $ | 特殊性质 | 分值 |
|---|---|---|---|
| 1 | 101010 | 202020 | |
| 2 | 202020 | 202020 | |
| 3 | 505050 | bi≥0b_i\ge 0bi≥0 | 101010 |
| 4 | 505050 | 202020 | |
| 5 | 100100100 | 303030 |
思路
单纯型法!
代码见下
#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;
}

浙公网安备 33010602011771号