UOJ #179. 线性规划

http://uoj.ac/problem/179

 

分析:

  单纯形算法。

 

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 
 5 inline int read() {
 6     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
 7     for (;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
 8 }
 9 
10 const int N = 25;
11 const double eps = 1e-8;
12 double a[N][N], ans[N];
13 int B[N<<1], n, m;
14 /*
15 a[0][i] -> ci 目标函数中第i个元素系数
16 a[i][0] -> bi 第i条约束中小于等于的数 
17 a[i][j] -> Aij 第i条约束中第j个元素的系数
18 最大化 sigma(ci*xi),i∈N
19 约束 xj=bj-sigma(aji*xi) ,j∈B
20 */
21 void Pivot(int l,int e) {
22     swap(B[n+l], B[e]); // 交换基本变量(n+l)与非基本变量(e) 
23     double t = a[l][e];
24     a[l][e] = 1;
25     for (int j=0; j<=n; ++j) a[l][j] /= t;
26     for (int i=0; i<=m; ++i) 
27         if (i !=l && abs(a[i][e]) > eps) {
28             t = a[i][e];
29             a[i][e] = 0;
30             for (int j=0; j<=n; ++j) a[i][j] -= t * a[l][j];
31         }
32 }
33 bool Simplex() {
34     while (true) {
35         int l = 0, e = 0;
36         double mn = 1e18;
37         for (int j=1; j<=n; ++j) 
38             if (a[0][j] > eps) {e = j; break;}
39         if (!e) return true;
40         for (int i=1; i<=m; ++i) 
41             if (a[i][e] > eps && a[i][0]/a[i][e] < mn) 
42                 mn = a[i][0] / a[i][e], l = i; // 找到约束最紧的 
43         if (!l) {
44             puts("Unbounded");
45             return false;
46         }
47         Pivot(l,e);
48     }
49 }
50 /*
51 初始化
52 方法一:引入一个辅助线性规划 要求最大化-x0
53 约束为 xj=bj-sigma(aji*xi)+x0 ,j∈B然后用x0替换bj为负的约束
54 下面的是方法二:
55 在bi为负的时候,把所有基变量设为0不是一组合法的初始解
56 所以选择一个bi为负的基变量x[i+n]
57 然后在该约束右边找一个系数为正(即原系数为负)的非基变量进行Pivot操作
58 如果没有系数为正显然就无解了
59 */
60 bool init() {
61     while (true) {
62         int e = 0, l = 0;
63         for (int i=1; i<=m; ++i) 
64             if (a[i][0] < -eps && (!l || (rand() & 1))) l = i;
65         if (!l) return true;
66         for (int j=1; j<=n; ++j) 
67             if (a[l][j] < -eps && (!e || (rand() & 1))) e = j;
68         if (!e) {
69             puts("Infeasible");
70             return false;
71         }
72         Pivot(l,e);
73     }
74 }
75 int main() {
76     n = read(), m = read();
77     int Type = read();
78     for (int i=1; i<=n; ++i) a[0][i] = read();
79     for (int i=1; i<=m; ++i) {
80         for (int j=1; j<=n; ++j) a[i][j] = read();
81         a[i][0] = read();
82     }
83     for (int i=1; i<=n; ++i) B[i] = i;
84     if (init() && Simplex()) {
85         printf("%.8lf\n",-a[0][0]);
86         if (Type) {
87             for (int i=1; i<=m; ++i) ans[B[i+n]] = a[i][0];
88             for (int i=1; i<=n; ++i) printf("%.8lf ",ans[i]);
89         }
90     }
91     return 0;
92 }

 

转载于:https://www.cnblogs.com/mjtcn/p/9373932.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值