- 一、背包问题
- 1.模型建立
- 2.代码实现
- 二、指派问题
- 1.模型建立
- 2.代码实现
- (1)输入目标函数系数
- (2)输入不等式约束
- (3)输入等式约束
- (4)调用函数求解
- 三、钢管切割问题
- 1.问题分析
- 2.模型建立
- (1)利用枚举法找到料头小于等于0.9的切割方法
- (2)得到目标函数与约束
- 3.代码实现
- (1)枚举法找出同一个原材料上所有的切割方法
- (2)线性整数规划问题的求解
一、背包问题
1.模型建立
2.代码实现
c = -[540 200 180 350 60 150 280 450 320 120]; % 目标函数的系数矩阵(最大化问题记得加负号)
intcon=[1:10]; % 整数变量的位置(一共10个决策变量,均为0-1整数变量)
A = [6 3 4 5 1 2 3 5 4 2]; b = 30; % 线性不等式约束的系数矩阵和常数项向量(物品的重量不能超过30)
Aeq = []; beq =[]; % 不存在线性等式约束
lb = zeros(10,1); % 约束变量的范围下限
ub = ones(10,1); % 约束变量的范围上限
%最后调用intlinprog()函数
[x,fval]=intlinprog(c,intcon,A,b,Aeq,beq,lb,ub)
fval = -fval
二、指派问题
1.模型建立
2.代码实现
(1)输入目标函数系数
clear;clc
c = [66.8 75.6 87 58.6 57.2 66 66.4 53 78 67.8 84.6 59.4 70 74.2 69.6 57.2 67.4 71 83.8 62.4]'; % 目标函数的系数矩阵(先列后行的写法)
intcon = [1:20]; % 整数变量的位置(一共20个决策变量,均为0-1整数变量)
(2)输入不等式约束
这里着重讲一下约束怎么写,这里的变量有20个,已经很男写了,在运用中可能会有更多,因此一个一个打是不太现实的,可以先将矩阵初始化,然后利用循环添加数值
% 线性不等式约束的系数矩阵和常数项向量(每个人只能入选四种泳姿之一,一共五个约束)
A = [1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0;0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0;0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0;0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1];
% A=zeros(5,20)
% j=1
% for i=1:5
% A(i,j:j+3)=1
% j=j+4
% end
b = [1;1;1;1;1];
(3)输入等式约束
每个项目只能由一名队员参加,在约束的体现上就是由4个单位矩阵拼接
Aeq = [1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0;0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0;0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0;0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1];
% Aeq = [eye(4),eye(4),eye(4),eye(4),eye(4)]; % 或者写成 repmat(eye(4),1,5)
beq = [1;1;1;1];
lb = zeros(20,1); % 约束变量的范围下限
ub = ones(20,1);
(4)调用函数求解
最终我们得到的是一个列向量,我们想将其转化为矩阵形式,但是reshape函数是按列将向量进行填充的,我们想要的是按行进行填充的效果。
如果直接将其转化为5行4列的矩阵会得到到错误的结果,因此先将其转成4行5列的矩阵,再将其转置即可
[x,fval] = intlinprog(c,intcon,A,b,Aeq,beq,lb,ub)
% reshape(x,4,5)'
% 0 0 0 1 甲自由泳
% 1 0 0 0 乙蝶泳
% 0 1 0 0 丙仰泳
% 0 0 1 0 丁蛙泳
% 0 0 0 0 戊不参加
三、钢管切割问题
1.问题分析
因为原材料的长度一共6.9m,我们可以先找到一种简单的,能够直接满足需求切割方式,然后再用枚举法找出比这种切割方式更好(剩余材料更少)的方法,进行整数规划求解。
原材料一共6.9m,用一根原材料可以切割2.9m,2.1m 和 1m 的圆钢各一根,这样需要100根原材料就可以达到我们的需求了。但我们知道,这样的方式是有很多浪费的,因为用这种方式所得的料头(剩余材料长度)为0.9m,这样做100次岂不是浪费了90m的原材料,这种方法难道没有意义了吗?
之所以提出这种不那么好但是有用的方法,就是以这种方法为基础,找出所有优于这种方法的切割方法,然后利用这些方法进行规划求解。
2.模型建立
(1)利用枚举法找到料头小于等于0.9的切割方法
(2)得到目标函数与约束
3.代码实现
(1)枚举法找出同一个原材料上所有的切割方法
由于6.9m的原材料最多只能切两根2.9m的圆钢,因此i的取值为0,1,2。其余同理,找出料头小于等于0.9m的满足要求的切割方法,进行输出
for i = 0: 2 % 2.9m长的圆钢的数量for j = 0: 3 % 2.1m长的圆钢的数量for k = 0:6 % 1m长的圆钢的数量if 2.9*i+2.1*j+1*k >= 6 && 2.9*i+2.1*j+1*k <= 6.9disp([i, j, k])endendend
end
(2)线性整数规划问题的求解
我们把这7种切割方法设为x1,x2.....,目标函数就是使用原材料的数目最小,而这7项求和即为原材料的数目。
不等式约束要求每种切割的原钢数目要大于等于100
c = ones(7,1); % 目标函数的系数矩阵
intcon=[1:7]; % 整数变量的位置(一共7个决策变量,均为整数变量)
A = -[1 2 0 0 0 0 1; 0 0 3 2 1 0 1;4 1 0 2 4 6 1]; % 线性不等式约束的系数矩阵
b = -[100 100 100]'; % 线性不等式约束的常数项向量
lb = zeros(7,1); % 约束变量的范围下限
[x,fval]=intlinprog(c,intcon,A,b,[],[],lb)