【BZOJ3265】志愿者招募加强版 线性规划 单纯形法 对偶原理
来源:互联网 发布:cad工程量计算软件 编辑:程序博客网 时间:2024/05/29 18:18
链接:
#include <stdio.h>int main(){ puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/45673079");}
题解:
这道题是线性规划求目标函数最小值 ,对偶原理转一下就成了单纯形算法求线性规划最大值。
单纯形法:
首先这篇博客缺失了很多证明,只能讲述单纯形法的实现。
// N个变量 M个限制double a[M][N]; // 这m个限制里变量的系数double b[M]; // 第i个限制加和 <=bidouble c[N]; // 目标函数里变量系数double ans; // 目标函数自带的系数void pivot(int x,int y); // 转轴操作void solve();
首先对于如下数据
3 3 2 3 41 1 2 21 2 3 51 3 3 2
我们可以得到以下的限制:
目标函数:
限制函数:
然后若
那么我们可以将式子表示为
状态 1: **************
目标函数:
限制函数:
然后在单纯形的过程中函数们的各系数得到改变的过程如下:
状态 1: **************
目标函数:
限制函数:
状态 2: **************
目标函数:
限制函数:
状态 3: **************
目标函数:
限制函数:
状态 4: **************
目标函数:
限制函数:
状态 5: **************
目标函数:
限制函数:
线性规划最终答案:17
单纯形思想:
其实就是每次找一个在目标函数中存在的变量,跟不在其中的某个变量交换一下,然后换来换去最终目标函数中所有变量系数都为负了,那么目标函数最后加的常数就是答案辣。
单纯形实现:
具体的实现过程呢?
struct Simplex{ int n,m; // n个变量、m个限制 double a[M][N],b[M],c[M],ans; void pivot(int x,int y) { int i,j; double t; b[x]/=a[x][y]; for(i=1;i<=n;i++)if(i!=y)a[x][i]/=a[x][y]; a[x][y]=1.0/a[x][y]; for(i=1;i<=m;i++)if(i!=x&&fabs(a[i][y])>eps) { b[i]-=a[i][y]*b[x],t=a[i][y]; for(j=1;j<=n;j++)a[i][j]-=t*a[x][j]; a[i][y]=-t*a[x][y]; } ans+=c[y]*b[x],t=c[y]; for(i=1;i<=n;i++)c[i]-=t*a[x][i]; c[y]=-t*a[x][y]; } double solve() { read(); double t; for(int i,x,y;;) { for(i=1;i<=m;i++)if(c[i]>eps){y=i;break;} if(i>m)return ans; for(t=inf,i=1;i<=m;i++) if(a[i][y]>eps&&t>b[i]/a[i][y]) x=i,t=b[i]/a[i][y]; if(t==inf)return t; else pivot(x,y); } }}simplex;
下面的实现里存在两个坑,请不要深究它们怎么证。
首先我们每次找一个标号最靠前的【坑1】目标函数中系数为正的变量
然后我们找这个变量在哪个限制里是”最紧”的【坑3】,即33、34、35这三行。
如果找不到任何一个”紧”的行,即
然后我们对此限制中的辅助变量和找到的
先把第
对偶原理:
如果要求最小值,那么我们把模型对偶一下就可以辣。【坑5】
即限制矩阵 【转置】 一下,然后目标函数的系数和每个限制的最终
【转置】 :矩阵的元素
对于证明坑的总结:
【坑1】为什么要找标号最小的?
根据Bland法则,这么做可以避免被卡死循环。
【坑2】为什么标号都是负的就表示找到了最优解?
表示无法理解为什么不能给某个存在负系数的变量转一转。
【坑3】为什么要找”最紧”的?
不知道不知道。
【坑4】为什么直接返回无界了?
不可以别的某个变量再来转一转,然后就回归有界?
【坑5】对偶原理是毛线?
天然坑,深坑。
代码:
#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 1010 // 变量个数#define M 10100 // 限制个数#define inf 1e9#define eps 1e-5using namespace std;struct Simplex{ int n,m; // n个变量、m个限制 double a[M][N],b[M],c[M],ans; void read() { int i,j,k,l,r; scanf("%d%d",&m,&n); for(i=1;i<=m;i++)scanf("%lf",&c[i]); for(i=1;i<=n;i++) { scanf("%d",&k); while(k--) { scanf("%d%d",&l,&r); for(j=l;j<=r;j++)a[i][j]=1.0; } scanf("%lf",&b[i]); } swap(n,m); } void pivot(int x,int y) { int i,j; double t; b[x]/=a[x][y]; for(i=1;i<=n;i++)if(i!=y)a[x][i]/=a[x][y]; a[x][y]=1.0/a[x][y]; for(i=1;i<=m;i++)if(i!=x&&fabs(a[i][y])>eps) { b[i]-=a[i][y]*b[x],t=a[i][y]; for(j=1;j<=n;j++)a[i][j]-=t*a[x][j]; a[i][y]=-t*a[x][y]; } ans+=c[y]*b[x],t=c[y]; for(i=1;i<=n;i++)c[i]-=t*a[x][i]; c[y]=-t*a[x][y]; } double solve() { read(); double t; for(int i,x,y;;) { for(i=1;i<=m;i++)if(c[i]>eps){y=i;break;} if(i>m)return ans; for(t=inf,i=1;i<=m;i++) if(a[i][y]>eps&&t>b[i]/a[i][y]) x=i,t=b[i]/a[i][y]; if(t==inf)return t; else pivot(x,y); } }}simplex;int main(){// freopen("test.in","r",stdin); printf("%d\n",(int)(simplex.solve()+eps)); return 0;}
- 【BZOJ3265】志愿者招募加强版 线性规划 单纯形法 对偶原理
- [单纯形+对偶] BZOJ3265: 志愿者招募加强版
- bzoj3265: 志愿者招募加强版 单纯形
- 【BZOJ3265】志愿者招募加强版【单纯形法】
- [线性规划 对偶原理 单纯形] BZOJ 3265 志愿者招募加强版
- [BZOJ3265]志愿者招募加强版(单纯形)
- [BZOJ3265]志愿者招募加强版
- bzoj3265 noi2008志愿者招募 【线性规划】
- BZOJ3265: 志愿者招募加强版&&1061: [Noi2008]志愿者招募
- BZOJ3265: 志愿者招募加强版&1061: [Noi2008]志愿者招募
- 【BZOJ】【P3265】【志愿者招募加强版】【题解】【单纯形法】
- [单纯形+对偶] BZOJ1061: [Noi2008]志愿者招募
- [bzoj1061][线性规划][单纯形][Noi2008]志愿者招募]
- BZOJ 3265 志愿者招募加强版 单纯形
- bzoj 3265 志愿者招募加强版 (单纯形)
- bzoj 3265: 志愿者招募加强版 (单纯形)
- 【BZOJ1061】[Noi2008]志愿者招募【单纯形法】
- BZOJ 3265 志愿者招募(BZOJ 1061)加强版 && BZOJ 3112 [Zjoi2013]防守战线 单纯形
- 原生类型的处理
- 实现core文件自动生成配置文件的方法
- 注册模块的错误解决
- Leetcode Single Number
- Android XML文件中引用资源的方法
- 【BZOJ3265】志愿者招募加强版 线性规划 单纯形法 对偶原理
- 几种开源TCPIP协议概述--LwIP,uIP,TinyTcp和uC/IP
- ActionBar(6)操作提供器ActionProvider及以ShareActionProvider演示
- java入门
- @Autowired
- js中如何实现继承
- 安卓给textView增加自定义的颜色
- 黑马程序员——Java练习笔记——面向对象
- Android中资源文件的使用