bzoj1061--线性规划

线性规划裸题。。。

根据题目很容易可以得到线性规划方程(以样例为例):

Min(2*x1+5*x2+2*x3)

x1+ 0+ 0>=2

x1+x2+ 0>=3

0+x2+x3>=4

x1,x2,x3>=0

再将方程对偶,得到:

Max(2*x1+3*x2+4*x3)

x1+x2+ 0<=2

0+x2+x3<=5

0+ 0+x3<=2

x1,x2,x3>=0

这就是线性规划的标准型了。

为了方便单纯型算法,加入变量x4,x5,x6:

Max(2*x1+3*x2+4*x3)

x4+x1+x2+ 0=2

x5+ 0+x2+x3=5

x6+ 0+ 0+x3=2

x1,x2,x3,x4,x5,x6>=0

这就是松弛型。显然此时最优解不变。

将松弛型写成矩阵的形式:

x1 x2 x3

x4  1  1  0  2

x5  0  1  1  5

x6  0  1  1  2

2   3  4  0(k)

当x1,x2,x3取0时,显然满足条件,此时答案为右下角的常数k

我们只需不断增大k,当k达到最大值时最优解就是k了。

那么怎么增大k呢?显然如果我们增大x1,答案会更优。

但x1不能无限制地增大,对于前3个方程,我们得到x1的限制:

1、x1<=2

2、x1无限制

3、x1无限制

我们选择最紧的一个限制1,将x1增大到它,再交换x1,x4。

交换之后再将某些系数改变,使其满足方程就可以了。

于是我们可以不断交换,直到矩阵最后一行的系数都不为正就可以了。最优解就是k。

具体看代码。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 using namespace std;
 6 #define N 1001
 7 #define M 10001
 8 #define DB double
 9 #define Eps 1e-7
10 #define INF 0x3f3f3f3f3f3f3f3f
11 DB a[M][N],c[N],b[M],Ans,Tmp;
12 int i,j,n,m,l,r,x;
13 inline void Pivot(int x,int y){                                //转轴操作,使矩阵满足方程
14     b[x]/=a[x][y];
15     for(int i=1;i<=n;i++)if(i!=y)a[x][i]/=a[x][y];
16     a[x][y]=1/a[x][y];
17     for(int i=1;i<=m;i++)
18     if(i!=x&&fabs(a[i][y])>Eps){
19         b[i]-=a[i][y]*b[x];
20         for(int j=1;j<=n;j++)if(j!=y)a[i][j]-=a[i][y]*a[x][j];
21         a[i][y]*=-a[x][y];
22     }
23     Ans+=c[y]*b[x];
24     for(int i=1;i<=n;i++)if(i!=y)c[i]-=c[y]*a[x][i];
25     c[y]*=-a[x][y];
26 }
27 inline DB Simplex(){
28     while(1){                                                   //不断交换
29         for(i=1;i<=n;i++)if(c[i]>Eps)break;
30         if(i>n)return Ans;
31         Tmp=INF;
32         for(j=1;j<=m;j++)
33         if(a[j][i]>Eps&&b[j]/a[j][i]<Tmp)Tmp=b[j]/a[j][i],x=j;
34         if(Tmp==INF)return INF;
35         Pivot(x,i);                                         //交换第x行,第i列
36     }
37 }
38 int main()
39 {
40     scanf("%d%d",&n,&m);
41     for(i=1;i<=n;i++)scanf("%lf",&c[i]);
42     for(i=1;i<=m;i++){
43         scanf("%d%d%lf",&l,&r,&b[i]);
44         for(j=l;j<=r;j++)a[i][j]=1;
45     }
46     printf("%d",(int)(Simplex()+0.5));
47 }

bzoj1061

时间: 2024-11-02 11:03:54

bzoj1061--线性规划的相关文章

【bzoj1061】[NOI2008]志愿者招募 线性规划与费用流

题目描述 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者.经过估算,这个项目需要N 天才能完成,其中第i 天至少需要Ai 个人.布布通过了解得知,一共有M 类志愿者可以招募.其中第i 类可以从第Si 天工作到第Ti 天,招募费用是每人Ci 元.新官上任三把火,为了出色地完成自己的工作,布布希望用尽量少的费用招募足够的志愿者,但这并不是他的特长!于是布布找到了你,希望你帮他设计一种最优的招募方案. 输入

线性规划费用流解法(Bzoj1061: [Noi2008]志愿者招募)

题面 传送门 Sol 线性规划费用流解法用与求解未知数为非负数的问题 这道题可以列出一堆形如 \(x[i]+x[j]+x[k]+...>=a[p]\) 的不等式 我们强行给每个式子减去一个东西,使他变成这样 \(x[i]+x[j]+x[k]+...-y[p]==a[p]\) 然后相邻两个式子差分一下 把每个式子看成一个点 那么这样后,在这个题中所有的未知数只会出现在一个方程中 等式左边符号是正的向符号为负的方程连边,费用为代价,如果是补的未知数\(y\),那么费用为零 右边的数是正的连\(s\)

线性规划 单纯形

求解线性规划最优解问题(全部转化成约束条件<=(非负条件可以是>=),并且求最大值问题) bzoj1061 志愿者招募 题目大意:给定n天,每天需要志愿者ai人:m类志愿者,从si-ti天工作,每人要ci元.求最小费用. 思路:根据题意可以列出目标函数是min sigma(i=1~m)cixi,约束条件是 sigma(i=1~m)Aijxi>=aj(j=1~n)(Aij表示这一天志愿者能否工作),xi>=0.这个问题如果*-1转化的话,可能要求解辅助约束.所以可以用对偶问题来解决,

【bzoj1283】序列 线性规划与费用流

题目描述 给出一个长度为 的正整数序列Ci,求一个子序列,使得原序列中任意长度为 的子串中被选出的元素不超过K(K,M<=100) 个,并且选出的元素之和最大. 输入 第1行三个数N,m,k. 接下来N行,每行一个字符串表示Ci. 输出 最大和. 样例输入 10 5 3 4 4 4 6 6 6 6 6 4 4 样例输出 30 题解 线性规划与费用流 关于线性规划与费用流的具体讲解参见 bzoj1061 . 这道题和那道差不多,都是给出一大堆限制条件,每个变量在限制条件中的出现是连续的. 所以我们

线性规划初探

看完<算法导论>肯定会写单纯形 因为单纯形不仅好写而且<算法导论>里讲的很清楚 附赠uoj179的模板一个 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<stdlib.h> 7 8 using namespace std; 9 const

数学(线性规划): ZJOI2013 防守战线

偷懒用的线性规划. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int maxr=1010; 6 const int maxc=10010; 7 8 int n,m,nxt[maxc]; 9 int a[maxr][maxc]; 10 11 12 void Pivot(int l,int e){ 13 int pre=maxc-

【网络流】线性规划的最小割建模方式

前几天在师大附中听课,大概了解了一些关于网络流的建模方式,然后今天上午做了一些题目,在这里总结一下. 最小割的线性规划建模方式: 有一些0/1变量Xi,怎么怎么样之后会消耗某些代价或者获得某些利益,而最后的总收益可以写成如下的形式: min{ Σmax{Xi-Xj,0}*Wi } 其中Wi必须是正数. 那么假设源为1,汇为0,就将Xi连一条流量为Wi的边到Xj. 如果有形如1-Xi之类的形式就是从源向Xi连边,Xi-0这种形式就是Xi向汇点连边. 那么如果Wi是负数怎么办? 比如Xi*Wi(Wi

线性规划问题中的差分约束与最短路径

先给一个线性规划的定义: 在通用的线性规划问题中,我们通常给定一个m*n的矩阵A,一个m维的向量和一个n维向量(权值函数).我们希望找到一个n维向量x,使得在由Ax<=b给定的m个约束条件下优化目标函数ci*xi,这里的优化是指目标函数的取值最大. 根据矩阵乘法,我们大概脑补出这样一幅图 ps:上图中<号应为<=号(我会告诉你是我懒得改 ) 通过化简我们得到 x1-x3<=b1;x3<=b2;x2-x3<=b3; 这跟我们的最短路径有什么关系呢? 在最短路径的三角不等式

UOJ#179. 线性规划[模板]

传送门 http://uoj.ac/problem/179 震惊,博主竟然还不会线性规划! 单纯形实在学不会啊……背个板子当黑盒用…… 学(chao)了NanoApe dalao的板子 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 using namespace std; 7 const d

matlab绘图--线性规划图解法示意

matlab绘图--线性规划图解法示意 图解法 matlab绘图 区域填充 线性规划问题: matlab绘图 L1=[4,0;4,4]; plot(L1(:,1),L1(:,2));hold on  text(4.1,3.5,'x_1=4','color','b');  L2=[0 3;5 3];  plot(L2(:,1),L2(:,2));hold on  text(0.8,3.1,'x_2=3','color','b');  L3=[0 2.4;5 0.4];  plot(L3(:,1),