【UOJ 179】 #179. 线性规划 (单纯形法)
补充那一列修改方法:
对于第i行:
xi=bi−∑Aij∗xj
=bi-\sum_{j!=e} Aij*xj-Aie*xe
Pivot后应该是: =bi-\sum_{j!=e} Aij*xj-Aie*xl
假设第l行已经算对转轴后的系数
则xl=bl-\sum Alj*xj
所以xi=bi-\sum_{j!=e} Aij*xj-Aie*(bl-\sum Alj*xj)
=bi-Aie*bl-\sum_{j!=e}(Aij-Aie*Alj)*xj-(0-Aie*Alj*xj)
观察变化:
可以看出,所有系数只要-Aie*Alj就好了的。因为Aie会在过程中变化,所以一开始先存起来,然后置为0。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<ctime> using namespace std; #define Maxn 25 const double eps=0.00000001,INF=1e15; int n,m; int id[Maxn*2]; double a[Maxn][Maxn]; //第一维是限制,B集合 //第二维是元素,N集合 //a[0][xx] -> c 目标函数系数 //a[xx][0] -> b 限制等式常数 //a[xx][yy] -> A 限制等式系数向量 //最大化 sigma(ci*xi),i属于N //限制 xj=bj-sigma(aji*xi) ,j属于B double myabs( double x) { return x>0?x:-x;} void Pivot( int l, int e) { //转轴l和e swap(id[n+l],id[e]); double t=a[l][e];a[l][e]=1; for ( int j=0;j<=n;j++) a[l][j]/=t; for ( int i=0;i<=m;i++) if (i!=l&&myabs(a[i][e])>eps) { t=a[i][e];a[i][e]=0; for ( int j=0;j<=n;j++) a[i][j]-=a[l][j]*t; } } //初始化-辅助问题 bool init() { while (1) { int e=0,l=0; for ( int i=1;i<=m;i++) if (a[i][0]<-eps&&(!l||(rand()&1))) l=i; if (!l) break ; for ( int j=1;j<=n;j++) if (a[l][j]<-eps&&(!e||(rand()&1))) e=j; if (!e) {printf( "Infeasible\n" ); return 0;} Pivot(l,e); } return 1; } //最优化 bool simplex() { while (1) { int l=0,e=0; double mn=INF; for ( int j=1;j<=n;j++) if (a[0][j]>eps) {e=j; break ;} if (!e) break ; //如果目标变量c都小于0 找到答案 for ( int i=1;i<=m;i++) if (a[i][e]>eps&&a[i][0]/a[i][e]<mn) mn=a[i][0]/a[i][e],l=i; //找a[i][0]/a[i][e]最小的i进行转轴 if (!l) {printf( "Unbounded\n" ); return 0;} //如果所有的a[i][e]都小于0,说明最优值正无穷 Pivot(l,e); } return 1; } double ans[Maxn]; int main() { srand(time(0)); int t; scanf( "%d%d%d" ,&n,&m,&t); for ( int i=1;i<=n;i++) scanf( "%lf" ,&a[0][i]); for ( int i=1;i<=m;i++) { for ( int j=1;j<=n;j++) scanf( "%lf" ,&a[i][j]); scanf( "%lf" ,&a[i][0]); } for ( int i=1;i<=n;i++) id[i]=i; if (init()&&simplex()) { printf( "%.8lf\n" ,-a[0][0]); if (t) { for ( int i=1;i<=m;i++) ans[id[n+i]]=a[i][0]; for ( int i=1;i<=n;i++) printf( "%.8lf " ,ans[i]); } } return 0; } |
2017-03-14 21:01:07
分类:
单纯形法
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· DeepSeek火爆全网,官网宕机?本地部署一个随便玩「LLM探索」
· 开发者新选择:用DeepSeek实现Cursor级智能编程的免费方案
· 【译】.NET 升级助手现在支持升级到集中式包管理
· 独立开发经验谈:如何通过 Docker 让潜在客户快速体验你的系统
· Tinyfox 发生重大改版