單純形法與對偶定理
阿新 • • 發佈:2021-12-15
這貌似是運籌學的一個比較有趣的問題型別
不過介於我水平太低(只會背背板子)
在此記錄
單純形法
一般oi中遇到的線性規劃問題都長這樣
比如某一些網路流問題,以及二分圖最大權匹配啥的,結合對偶定理,可以有很多很強的結論
以及一個最小費用流的線性規劃式子
現在考慮怎麼做這類問題
不妨先引入一個基變數(鬆弛變數)
比如說現在的係數矩陣是
比如說現在的係數矩陣是
這樣可以吧\(x_{i , n + 1}\)
之後就可以用這個過程來時目標函式有最大值
有一個例題吧
很容易列出線性規劃式子
\[\left\{ \begin{matrix} max:c_1 * x_1 + c_2 * x_2 + ... + c_n *x_n\\ a_{11} * x_1 + a_{12} * x_2 + ... + a_{1n} * x_n <= b_1\\ .\\ .\\ a_{m1} * x_1 + a_{m2} * x_2 + ... + a_{mn} * x_n <= b_m\\ \end{matrix} \right. \]就是一個板子題
#include<bits/stdc++.h> #define MAXN 500 #define eps 1e-7 typedef double ll; const ll inf = 1e18; using namespace std; int n,m; ll a[MAXN][MAXN]; int id[MAXN]; void out(){ for(int i = 1 ; i <= n ; i++)printf("%.2f " , a[0][i]); puts(""); for(int i = 1 ; i <= m ; i++){ for(int j = 1 ; j <= n ; j++){ printf("%.2f " , a[i][j]); } printf("%.2f " , a[i][0]); puts(""); } } void plot(int x , int y){ swap(id[x + n] , id[y]); double t = a[x][y]; a[x][y] = 1; for(int j = 0 ; j <= n ; j++)a[x][j] /= t; for(int i = 0 ; i <= m ; i++){ if(i == x || a[i][y] < eps)continue; t = a[i][y] , a[i][y] = 0; for(int j = 0 ; j <= n ; j++)a[i][j] -= a[x][j] * t; } } bool simplex(){ for(int i = 1 ; i <= n ; i++)id[i] = i; int x = 0, y = 0; int cnt = 0; ll minl; while(1){ x = y = 0 , minl = inf; cnt++; for(int i = 1 ; i <= n ; i++)if(a[0][i] > eps){x = i;break;} if(!x)break; for(int i = 1 ; i <= m ; i++)if(a[i][x] > eps && minl > a[i][0] / a[i][x])minl = a[i][0] / a[i][x] , y = i; if(!y) {puts("Unbounded"); return false;} plot(y , x); } return true; } int main(){ while(scanf("%d%d",&n,&m) == 2){ memset(a , 0 ,sizeof(a)); for(int i = 1 ; i <= n ; i++)cin>>a[0][i]; for(int i = 1 ; i <= m ; i++){ for(int j = 1 ; j <= n ; j++)cin>>a[i][j]; cin>>a[i][0]; } simplex(); printf("Nasa can spend %d taka.\n",(int)ceil(-a[0][0]*m)); } }
對偶定理
很容易寫出線性規劃的模型,及其對偶
其係數矩陣為原係數矩陣的轉置
原問題有無界解等價於對偶問題無可行解
但是對偶問題無可行解時,原問題可能為無界解或者無可行解
剩下的很多擴充套件內容可以看這個
https://www.cnblogs.com/TianyiQ/p/linear-programming.html