题目链接
题解
引入基向量(x_{i + n}),将约束(sum_{i = 1}^{m}a_{ij}x_j leq b_i) 写为 $x_{i + n} = b_i - sum_{i = 1}^m a_{ij} x_j $
目标函数 $sum_{i = 1}^n C_i x_i $ 当存在 $ r,c$ 满足 (C_c>0,B_r > 0,a_{rc} > 0) ,把(x_c)作为第(r)个限制的基向量,得到$x_c = B_r - sum_{c geq j}a_{rj}x_j - x_{r + n} $
带入目标函数,非基向量取(0),一定可使目标函数增大,同时把其他约束中的(x_c)替换。
当所有的(B_r > 0)时一定能得到零解,存在(B_r < 0),在限制中找到一个小于(0)的(a_rc)的(x_c)带换为基向量,可以使(B_r >0) $x_i > 0 $
建议去看集训队论文
不过,为什么过不了
代码
#include<bits/stdc++.h>
using namespace std;
#define eps 1e-8
#define INF 1e9
inline int read() {
int x = 0,f = 1;
char c = getchar();
while(c < '0' ||c > '9'){ if(c == '-')f = - 1; c = getchar();}
while(c <= '9' &&c >= '0')x = x * 10 + c - '0',c = getchar();
return x * f;
}
int n,m,type,id[57];
double a[27][27],ans[57];
void pivot(int r,int c) { // swap basic varivle and nonbasic variable
swap(id[r + n],id[c]);
double t = a[r][c];a[r][c] = 1;
for(int i = 0;i <= n;++ i) a[r][i] /= t;
for(int i = 0;i <= m;++ i)
if(fabs(a[i][c]) > eps && i != r) {
t = a[i][c];a[i][c] = 0 ;
for(int j = 0;j <= n;++ j) a[i][j] -= t * a[r][j];
}
}
bool init() {
for(int r,c;;) {
r = c = 0;
for(int i = 1;i <= m;++ i)
if(a[i][0] < -eps && (!r || rand() & 1)) r = i;
if(!r) return 1;
for(int i = 1;i <= n;++ i)
if(a[r][i] < -eps && (!c || rand() & 1)) c = i;
if(!c) return puts("Infeasible") , 0;
pivot(r,c);
}
}
bool simplex() {
for(int r,c;;) {
r = c = 0;
for(int i = 1;i <= n;++ i)// C[c] > 0;
if(a[0][i] > eps) {c = i;break;}
if(!c)return 1;
double mn = INF; //找约束最紧的正系数a[r][c]
for(int i = 1;i <= m;++ i)
if(a[i][c] > eps && a[i][0] / a[i][c] < mn) r = i,mn = a[i][0] / a[i][c];
if(! r) return puts("Unbounded"),0;
pivot(r,c);
}
}
int main() {
srand(20020711);
n = read(),m = read(),type = read();
for(int i = 1;i <= n;++ i) a[0][i] = read(); //C[i]
for(int i = 1;i <= m;++ i) {
for(int j = 1;j <= n;++ j) a[i][j] = read();
a[i][0] = read(); //B[i]
}
for(int i = 1;i <= n;++ i) id[i] = i;
if(init() && simplex()) {
printf("%.8lf
",-a[0][0]);
if(type) {
for(int i = 1;i <= m;++ i) ans[id[i + n]] = a[i][0]; //成为基变量的xi取值即为bi,非基变量上的xi取0.
for(int i = 1;i <= n;++ i) printf("%.8lf ",ans[i]);
}
}
return 0;
}