2014高教社杯全国大学生数学建模竞赛D题目
题目描述
储药柜的结构类似于书橱,通常由若干个横向隔板和竖向隔板将储药柜分割成若干个储药槽(如图1所示)。为保证药品分拣的准确率,防止发药错误,一个储药槽内只能摆放同一种药品。药品在储药槽中的排列方式如图2所示。药品从后端放入,从前端取出。一个实际储药柜中药品的摆放情况如图3所示。
为保证药品在储药槽内顺利出入,要求药盒与两侧竖向隔板之间、与上下两层横向隔板之间应留2mm的间隙,同时还要求药盒在储药槽内推送过程中不会出现并排重叠、侧翻或水平旋转。在忽略横向和竖向隔板厚度的情况下,建立数学模型,给出下面几个问题的解决方案。
- 药房内的盒装药品种类繁多,药盒尺寸规格差异较大,附件1中给出了一些药盒的规格。请利用附件1的数据,给出竖向隔板间距类型最少的储药柜设计方案,包括类型的数量和每种类型所对应的药盒规格。
- 药盒与两侧竖向隔板之间的间隙超出2mm的部分可视为宽度冗余。增加竖向隔板的间距类型数量可以有效地减少宽度冗余,但会增加储药柜的加工成本,同时降低了储药槽的适应能力。设计时希望总宽度冗余尽可能小,同时也希望间距的类型数量尽可能少。仍利用附件1的数据,给出合理的竖向隔板间距类型的数量以及每种类型对应的药品编号。
- 考虑补药的便利性,储药柜的宽度不超过2.5m、高度不超过2m,传送装置占用的高度为0.5m,即储药柜的最大允许有效高度为1.5m。药盒与两层横向隔板之间的间隙超出2mm的部分可视为高度冗余,平面冗余=高度冗余×宽度冗余。在问题2计算结果的基础上,确定储药柜横向隔板间距的类型数量,使得储药柜的总平面冗余量尽可能地小,且横向隔板间距的类型数量也尽可能地少。
- 附件2给出了每一种药品编号对应的最大日需求量。在储药槽的长度为1.5m、每天仅集中补药一次的情况下,请计算每一种药品需要的储药槽个数。为保证药房储药满足需求,根据问题3中单个储药柜的规格,计算最少需要多少个储药柜。
提出关键点
一个储药槽内只能摆放同一种药品。
要求药盒与两侧竖向隔板之间、与上下两层横向隔板之间应留2mm的间隙,同时还要求药盒在储药槽内推送过程中不会出现并排重叠、侧翻或水平旋转。在忽略横向和竖向隔板厚度的情况下,建立数学模型。
建立数学模型
模型一:储药槽和药盒关系模型
已知药盒长宽高分别是 a , b , c a,b,c a,b,c毫米,设计储药槽长宽高分别是 x , y , z x,y,z x,y,z毫米。
要求药盒在储药槽内推送过程中不会出现:
1.并排重叠 ,
即储药槽高度不能高于两倍的药盒高,储药槽宽度不能高于两倍的药盒宽
{ z < 2 c y < 2 b \begin{cases}z\lt 2c\\y \lt 2b\end{cases} {z<2cy<2b
2.侧翻,
如上图,红色为药盒,分两种情况,情况一:绿色为储药槽;情况二:黑色为储药槽。
假设考虑的是不能完全侧翻情况,那么模型为:
{ z < b 2 + c 2 + M ( 1 − μ ) y < b 2 + c 2 + M ( 1 − v ) μ + v ≥ 1 μ , v ∈ { 0 , 1 } \begin{cases} z\lt \sqrt{b^2+c^2} + M(1-\mu)\\ y \lt \sqrt{b^2+c^2} + M(1-v)\\ \mu + v \ge 1\\ \mu,v \in \set{0,1} \end{cases} ⎩ ⎨ ⎧z<b2+c2+M(1−μ)y<b2+c2+M(1−v)μ+v≥1μ,v∈{0,1}
其中 M M M为定值,并且 M ≥ b 2 + c 2 M \ge \sqrt{b^2+c^2} M≥b2+c2
考虑实际情况,假设侧翻角度超过 45 45 45度即为侧翻
观察上图,下方绿线和红线夹角为45度时为极限角度可以得到:
y = 2 2 ( a + b ) y = \dfrac{\sqrt{2}}{2}(a+b) y=22(a+b)
并且侧翻时侧面解刨图来看,长方形的一个点会和储药槽底部接触,模拟物体旋转过程发现当长方形的对角线和底部垂直时候,整个物体触顶高度达到最高值。也就是说如果储药槽设计高度低于物体的对角线长度物体将无法侧翻
可以得到模型:
{ z < b 2 + c 2 + M ( 1 − μ ) y < 2 2 ( a + b ) + M ( 1 − v ) μ + v ≥ 1 μ , v ∈ { 0 , 1 } \begin{cases} z\lt \sqrt{b^2+c^2} + M(1-\mu)\\ y \lt \dfrac{\sqrt{2}}{2}(a+b) + M(1-v)\\ \mu + v \ge 1\\ \mu,v \in \set{0,1} \end{cases} ⎩ ⎨ ⎧z<b2+c2+M(1−μ)y<22(a+b)+M(1−v)μ+v≥1μ,v∈{0,1}
其中 M M M为定值,并且 M ≥ max ( b 2 + c 2 , 2 2 ( a + b ) ) M \ge \max{(\sqrt{b^2+c^2},\dfrac{\sqrt{2}}{2}(a+b))} M≥max(b2+c2,22(a+b))
将45度推广为 α \alpha α度(准确来讲是物体抬起的角度),模型将变为
{ z < b 2 + c 2 + M ( 1 − μ ) y < b cos α + c cos ( π 2 − α ) + M ( 1 − v ) μ + v ≥ 1 μ , v ∈ { 0 , 1 } \begin{cases} z\lt \sqrt{b^2+c^2} + M(1-\mu)\\ y \lt b\cos{\alpha}+c\cos{(\dfrac{\pi}{2}-\alpha)} + M(1-v)\\ \mu + v \ge 1\\ \mu,v \in \set{0,1} \end{cases} ⎩ ⎨ ⎧z<b2+c2+M(1−μ)y<bcosα+ccos(2π−α)+M(1−v)μ+v≥1μ,v∈{0,1}
其中 M M M为定值,并且 M ≥ max ( b 2 + c 2 , b cos α + c cos ( π 2 − α ) ) M \ge \max{(\sqrt{b^2+c^2},b\cos{\alpha}+c\cos{(\dfrac{\pi}{2}-\alpha)})} M≥max(b2+c2,bcosα+ccos(2π−α))
3.水平旋转 ,
实际上和侧翻的情况一类似,只是宽和高变成了长和宽
设物体水平旋转了 α \alpha α度就称为水平旋转了
y < b cos α + a cos ( π 2 − α ) y \lt b\cos{\alpha}+a\cos{(\dfrac{\pi}{2}-\alpha)} y<bcosα+acos(2π−α)
要求药盒与两侧竖向隔板之间、与上下两层横向隔板之间应留2mm的间隙
{ z ≥ c + 2 y ≥ b + 2 \begin{cases} z\ge c+2\\ y \ge b + 2 \end{cases} {z≥c+2y≥b+2
建立解决问题的数学模型
问题一
假设已知所有盒装药品所需的储药槽宽度 x x x约束,和所有盒装药品总数 N N N
即 a i ≤ x i < b i , i = 1 , 2 , 3... N a_i\le x_i\lt b_i , i = 1,2,3...N ai≤xi<bi,i=1,2,3...N
那么
解决模型一:
设 y j y_j yj为第 j j j种竖向隔板间距类型大小
g i j g_{ij} gij表示第 i i i种药盒可不可以放进第 j j j种药槽里面
{ min ∑ j = 1 M f j a i g i j ≤ y j f j < b i + M ′ ( 1 − g i j ) ∑ j = 1 M g i j ≥ 1 f j , g i j ∈ { 0 , 1 } i = 1 , 2 , 3 , . . . N , j = 1 , 2 , 3 , . . . M \begin{cases} \min \displaystyle\sum_{j=1}^M f_j\\ a_ig_{ij} \le y_jf_j \lt b_i+M'(1-g_{ij})\\ \displaystyle\sum_{j=1}^M g_{ij} \ge 1\\ f_j , g_{ij} \in \set{0,1}\\ i = 1,2,3,...N , j = 1,2,3,...M \end{cases} ⎩ ⎨ ⎧minj=1∑Mfjaigij≤yjfj<bi+M′(1−gij)j=1∑Mgij≥1fj,gij∈{0,1}i=1,2,3,...N,j=1,2,3,...M
M ′ ≥ max i = 1 N b i M'\ge \max_{i=1}^Nb_i M′≥maxi=1Nbi
这种模型就要先求出所有可能为竖向隔板间距类型的大小
解决模型二:
我们可以得出第 i i i种药盒能放进的药槽都得出来,记做 d i j d_{ij} dij
如果 d i j = 1 d_{ij}=1 dij=1表示得出第 i i i种药盒能放进第 j j j种药槽,反之不能
{ min ∑ j = 1 M f j ∑ j = 1 M d i j f j > 1 f j , g i j ∈ { 0 , 1 } i = 1 , 2 , 3 , . . . N , j = 1 , 2 , 3 , . . . M \begin{cases} \min \displaystyle\sum_{j=1}^M f_j\\ \displaystyle\sum_{j=1}^M d_{ij}f_j \gt 1\\ f_j , g_{ij} \in \set{0,1}\\ i = 1,2,3,...N , j = 1,2,3,...M \end{cases} ⎩ ⎨ ⎧minj=1∑Mfjj=1∑Mdijfj>1fj,gij∈{0,1}i=1,2,3,...N,j=1,2,3,...M
解决模型三:
{ a i g i ≤ x j < b i g i max ∑ i = 1 N g i f j , g i ∈ { 0 , 1 } i = 1 , 2 , 3 , . . . N , j = 1 , 2 , 3 , . . . M \begin{cases} a_ig_i \le x_j \lt b_ig_i\\ \max \displaystyle\sum_{i=1}^N g_i\\ f_j , g_i \in \set{0,1}\\ i = 1,2,3,...N , j = 1,2,3,...M \end{cases} ⎩ ⎨ ⎧aigi≤xj<bigimaxi=1∑Ngifj,gi∈{0,1}i=1,2,3,...N,j=1,2,3,...M
不断增加 M M M的值,直到答案 ∑ i = 1 N g i ≥ N \displaystyle\sum_{i=1}^N g_i \ge N i=1∑Ngi≥N,就求出其中一组解
问题二
简单来说就是要求所有 药盒与两侧竖向隔板之间的间隙超出2mm的部分 之和最小
利用上一问的模型三:
{ a i g i ≤ x j < b i g i max ∑ i = 1 N g i f j , g i ∈ { 0 , 1 } i = 1 , 2 , 3 , . . . N , j = 1 , 2 , 3 , . . . M \begin{cases} a_ig_i \le x_j \lt b_ig_i\\ \max \displaystyle\sum_{i=1}^N g_i\\ f_j , g_i \in \set{0,1}\\ i = 1,2,3,...N , j = 1,2,3,...M \end{cases} ⎩ ⎨ ⎧aigi≤xj<bigimaxi=1∑Ngifj,gi∈{0,1}i=1,2,3,...N,j=1,2,3,...M
其中 M M M的临界值 M 1 M_1 M1在问题一已经求出
所以就可以规定 M ≥ M 1 M\ge M_1 M≥M1
同问题一的假设:
假设已知所有盒装药品所需的储药槽宽度 x x x约束,和所有盒装药品总数 N N N
即 a i ≤ x i < b i , i = 1 , 2 , 3... N a_i\le x_i\lt b_i , i = 1,2,3...N ai≤xi<bi,i=1,2,3...N
观察模型一:储药槽和药盒关系模型中的所有约束条件,发现 a i a_i ai只能是药盒的宽度加两毫米,为已知量
那么药盒与两侧竖向隔板之间的间隙超出2mm的部分可以表示为:
x i − a i x_i - a_i xi−ai
因为还要约束两侧竖向隔板之间的间隙的种类,所以
m i n ∑ j = 1 M ∑ i = 1 N x j − a i , x j ≥ a i min \displaystyle\sum_{j=1}^M\displaystyle\sum_{i=1}^N x_j-a_i , x_j\ge a_i minj=1∑Mi=1∑Nxj−ai,xj≥ai
得到
模型一:
{ m i n ∑ j = 1 M ∑ i = 1 N x j − a i , x j ≥ a i a i g i ≤ x j < b i g i ∑ i = 1 N g i = N f j , g i ∈ { 0 , 1 } i = 1 , 2 , 3 , . . . N , j = 1 , 2 , 3 , . . . M \begin{cases} min \displaystyle\sum_{j=1}^M\displaystyle\sum_{i=1}^N x_j-a_i , x_j\ge a_i\\ a_ig_i \le x_j \lt b_ig_i\\ \displaystyle\sum_{i=1}^N g_i = N\\ f_j , g_i \in \set{0,1}\\ i = 1,2,3,...N , j = 1,2,3,...M \end{cases} ⎩ ⎨ ⎧minj=1∑Mi=1∑Nxj−ai,xj≥aiaigi≤xj<bigii=1∑Ngi=Nfj,gi∈{0,1}i=1,2,3,...N,j=1,2,3,...M
当然这种模型求解/优化都不容易
如果换个思路,在问题一已知有多少种两侧竖向隔板之间的间隙的种类了,并且求出了对应药盒对应的两侧竖向隔板之间的间隙,那么就可以把两侧竖向隔板之间的间隙相同的都分为一组,最后形成 M M M组药盒和对应的两侧竖向隔板之间的间隙
只需要每一组对应的两侧竖向隔板之间的间隙都取最小值,那么 M M M组加起来也就是所有 药盒与两侧竖向隔板之间的间隙超出2mm的部分 之和最小
那么
模型二:
{ a i g i ≤ x j < b i g i ∑ i = 1 N g i = N a i k j ≤ x j < b i k j m i n ∑ i = 1 N x j − a i k j , j = 1 , 2 , 3 , . . . M f j , g i , k j ∈ { 0 , 1 } i = 1 , 2 , 3 , . . . N , j = 1 , 2 , 3 , . . . M \begin{cases} a_ig_i \le x_j \lt b_ig_i\\ \displaystyle\sum_{i=1}^N g_i = N\\ a_ik_j \le x_j \lt b_ik_j\\ min \displaystyle\sum_{i=1}^N x_j-a_ik_j ,j = 1,2,3,...M\\ f_j , g_i , k_j\in \set{0,1}\\ i = 1,2,3,...N , j = 1,2,3,...M \end{cases} ⎩ ⎨ ⎧aigi≤xj<bigii=1∑Ngi=Naikj≤xj<bikjmini=1∑Nxj−aikj,j=1,2,3,...Mfj,gi,kj∈{0,1}i=1,2,3,...N,j=1,2,3,...M
发现模型二实际上就是模型一的改进,模型二利用0/1变量 k j k_j kj去定位药盒所对应的两侧竖向隔板之间的间隙的同时也是在解决模型一中$ x_j\ge a_i$条件
由此就可以得到一个"通用"的解决手段:
如果出现当 x i ≤ a j x_i\le a_j xi≤aj时候某个式子 f ( x i , a j ) f(x_i,a_j) f(xi,aj)才执行/成立
即 f ( x i , a j ) , x i ≤ a j f(x_i,a_j) , x_i\le a_j f(xi,aj),xi≤aj
假设为 u = { f ( x i , a j ) , x i ≤ a j 0 , x i > a j u = \begin{cases}f(x_i,a_j) , x_i\le a_j\\0,x_i\gt a_j\end{cases} u={f(xi,aj),xi≤aj0,xi>aj
这时候引入一个0/1变量 k i k_i ki
$ \begin{cases}u =f(x_i,a_jk_i)\x_i\le a_jk_j\end{cases}$
但要注意:
1. f ( x i , a j ) 改成 f ( x i , a j k i ) f(x_i,a_j)改成f(x_i,a_jk_i) f(xi,aj)改成f(xi,ajki)时候不能改变题目本意
2.之所以是 f ( x i , a j k i ) f(x_i,a_jk_i) f(xi,ajki)而不是 f ( x i , a j ) k i f(x_i,a_j)k_i f(xi,aj)ki,是因为最好不出现决策变量和决策变量相乘
3.如果非要用 f ( x i , a j ) k i f(x_i,a_j)k_i f(xi,aj)ki,需要将决策变量和决策变量相乘的模型重新转化为线性模型
问题三
储药柜的宽度不超过2.5m、高度不超过2m,传送装置占用的高度为0.5m,即储药柜的最大允许有效高度为1.5m。
假设已知所有盒装药品所需的储药槽宽度 x x x约束,和所有盒装药品总数 N N N
即 a i < x i < b i , i = 1 , 2 , 3... N a_i\lt x_i\lt b_i , i = 1,2,3...N ai<xi<bi,i=1,2,3...N
假设已知所有盒装药品所需的储药槽高度度 y y y约束,和所有盒装药品总数 N N N
即 c i < y i < d i , i = 1 , 2 , 3... N c_i\lt y_i\lt d_i , i = 1,2,3...N ci<yi<di,i=1,2,3...N
则:
储药柜的宽度不超过2.5m
∑ i = 1 N x i ≤ 2500 \displaystyle\sum_{i=1}^N x_i \le 2500 i=1∑Nxi≤2500
储药柜的最大允许有效高度为1.5m
∑ i = 1 N y i ≤ 1500 \displaystyle\sum_{i=1}^N y_i \le 1500 i=1∑Nyi≤1500
在问题二中宽度冗余为 ∑ i = 1 N x j − a i k j \displaystyle\sum_{i=1}^N x_j-a_ik_j i=1∑Nxj−aikj
同理我们也可以得到高度冗余为 ∑ i = 1 N y j − c i l j \displaystyle\sum_{i=1}^N y_j-c_il_j i=1∑Nyj−cilj
平面冗余=高度冗余×宽度冗余
即平面冗余为 ( ∑ i = 1 N x j − a i k j ) ( ∑ i = 1 N y j − c i l j ) (\displaystyle\sum_{i=1}^N x_j-a_ik_j)(\displaystyle\sum_{i=1}^N y_j-c_il_j) (i=1∑Nxj−aikj)(i=1∑Nyj−cilj)
要使横向隔板间距的类型数量也尽可能地少。我们可以利用问题一中的模型求出横向隔板间距的类型数量临界值 M 2 M_2 M2
{ a i g i ≤ x j < b i g i ∑ i = 1 N g i = N c i o i ≤ y k < d i o i ∑ i = 1 N o i = N a i h j ≤ x j < b i h j a i l k ≤ y k < b i l k m i n ( ∑ i = 1 N x j − a i h j ) ( ∑ i = 1 N y k − c i l k ) , j = 1 , 2 , 3 , . . . M f j , g i , h j , o i , l k ∈ { 0 , 1 } i = 1 , 2 , 3 , . . . N , j = 1 , 2 , 3 , . . . M , k = 1 , 2 , 3 , . . . K \begin{cases} a_ig_i \le x_j \lt b_ig_i\\ \displaystyle\sum_{i=1}^N g_i = N\\ c_io_i\le y_k\lt d_io_i\\ \displaystyle\sum_{i=1}^N o_i = N\\ a_ih_j \le x_j \lt b_ih_j\\ a_il_k \le y_k \lt b_il_k\\ min (\displaystyle\sum_{i=1}^N x_j-a_ih_j)(\displaystyle\sum_{i=1}^N y_k-c_il_k) ,j = 1,2,3,...M\\ f_j , g_i , h_j , o_i ,l_k\in \set{0,1}\\ i = 1,2,3,...N , j = 1,2,3,...M ,k = 1,2,3,...K \end{cases} ⎩ ⎨ ⎧aigi≤xj<bigii=1∑Ngi=Ncioi≤yk<dioii=1∑Noi=Naihj≤xj<bihjailk≤yk<bilkmin(i=1∑Nxj−aihj)(i=1∑Nyk−cilk),j=1,2,3,...Mfj,gi,hj,oi,lk∈{0,1}i=1,2,3,...N,j=1,2,3,...M,k=1,2,3,...K
问题四
已知第 i i i种药品编号对应的最大日需求量为 e i e_i ei和该药盒长度为 z i z_i zi毫米
在储药槽的长度为1.5m、每天仅集中补药一次的情况下,计算每一种药品需要的储药槽个数 x i x_i xi.
2 ∗ 1500 e i ∗ z i ≤ x i \dfrac{2*1500}{e_i*z_i}\le x_i ei∗zi2∗1500≤xi
这样就得出了所有药品对应所需储药槽个数 x i x_i xi。
在问题三中得出了一个药柜中所有横向(竖向)隔板间距的类型大小以及数量
同问题二从模型一到模型二的分组思路,每个药品其实对应一个组别
可以得出第 i i i种药品对应的组号 m i m_i mi,并且也知道组号 m i m_i mi对应的储药槽的个数 σ m i \sigma_{m_i} σmi
假设有 M M M组, x j i x_{ji} xji表示第 j j j组第 i i i种药品对应所需储药槽个数, σ j \sigma_j σj表示一个药柜种组号 j j j对应的储药槽的个数。
得到问题模型:
m i n ( m a x j = 1 M ∑ i = 1 N j x j i σ j ) min(max_{j=1}^M \dfrac{\displaystyle\sum_{i=1}^{N_j} x_{ji}}{\sigma_j}) min(maxj=1Mσji=1∑Njxji)
解决问题
问题一
模型一
在此之前已经初始化药盒长宽高分别放进数组length,weight,height中
处理一下数据,得到模型一的 a i a_i ai和 b i b_i bi,并且得到 y j y_j yj的所以可能取值
C++
void solve(){outFile.open("data.xlsx");if (!outFile.is_open()) {std::cerr << "无法打开文件" << std::endl;return ;}set<double>y;double a[N],b[N];for(int i=1;i<=1919;i++){a[i] = 2+weight[i];y.insert(a[i]);b[i] = min({2.0*weight[i],sqrt(weight[i]*weight[i] + height[i]*height[i]), sqrt(weight[i]*weight[i] + length[i]*length[i])});y.insert(b[i]);}for(int i=1;i<=1919;i++){outFile << a[i] << '\t';}outFile << '\n';for(int i=1;i<=1919;i++){outFile << b[i] << '\t';}outFile << '\n';for(auto x:y){outFile << x << '\t';}
}
这样我们就完成了上面讲的先求出所有可能为竖向隔板间距类型的大小
线性化:
void solve(){outFile.open("data.xlsx");if (!outFile.is_open()) {std::cerr << "无法打开文件" << std::endl;return ;}set<double>y;double a[N],b[N];for(int i=1;i<=1919;i++){a[i] = 2+weight[i];y.insert(a[i]);b[i] = min({2.0*weight[i],sqrt(weight[i]*weight[i] + height[i]*height[i]), sqrt(weight[i]*weight[i] + length[i]*length[i])});if((long long)b[i] == b[i])b[i]--;b[i] = (int)b[i];}for(int i=1;i<=1919;i++){outFile << a[i] << '\t';}outFile << '\n';for(int i=1;i<=1919;i++){outFile << b[i] << '\t';}outFile << '\n';cout << (int)y.size();for(auto x:y){outFile << x << '\t';}
}
解决模型一:
sets:aa/1..1919/:a,b;bb/1..47/:f,y;cc(aa,bb):g;
endsets
data:a=@ole("D:\homewrok\建模\储药柜的设计问题\data.xls",A1:BUU1);b=@ole("D:\homewrok\建模\储药柜的设计问题\data.xls",A2:BUU2);y=@ole("D:\homewrok\建模\储药柜的设计问题\data.xls",A3:AU3);
enddata
min=@sum(bb(j):f(j));
@for(aa(i):@for(bb(j):a(i)*g(i,j)<y(j)*f(j)));
@for(aa(i):@for(bb(j):b(i)+58*(1-g(i,j))>y(j)*f(j)));
@for(aa(i):@sum(bb(j):g(i,j))>1);
@for(cc(i,j):@bin(g(i,j)));
@for(bb(j):@bin(f(j)));
解得
Global optimal solution found.Objective value: 4.000000Objective bound: 4.000000Infeasibilities: 0.000000Extended solver steps: 0Total solver iterations: 13Variable Value Reduced CostF( 7) 1.000000 1.000000F( 22) 1.000000 1.000000F( 33) 1.000000 1.000000F( 47) 1.000000 1.000000
对应类型长度为:
18,33,44,58
模型二求解
C++预处理数据
void solve(){outFile.open("data2.xlsx");if (!outFile.is_open()) {std::cerr << "无法打开文件" << std::endl;return ;}double a[N],b[N];for(int i=1;i<=1919;i++){a[i] = 2+weight[i];b[i] = min({2.0*weight[i],sqrt(weight[i]*weight[i] + height[i]*height[i]), sqrt(weight[i]*weight[i] + length[i]*length[i])});b[i] = (int)(b[i]+0.5);}for(int i=1;i<=1919;i++){for(int j=12;j<=58;j++){int flag = a[i]<j&&j<b[i];outFile << flag << '\t';}outFile << '\n';}
}
sets:aa/1..1919/:;bb/1..47/:f;cc(aa,bb):d;
endsets
data:d = @ole("D:\homewrok\建模\储药柜的设计问题\data2.xls",A1:AU1919);
enddata
min=@sum(bb(j):f(j));
@for(aa(i):@sum(bb(j):d(i,j)*f(j))>1);
@for(bb(j):@bin(f(j)));
得到
Global optimal solution found.Objective value: 4.000000Objective bound: 4.000000Infeasibilities: 0.000000Extended solver steps: 0Total solver iterations: 58Variable Value Reduced CostF( 8) 1.000000 1.000000F( 23) 1.000000 1.000000F( 33) 1.000000 1.000000F( 47) 1.000000 1.000000
对应类型长度为:
19,34,44,58
纯编程求解:
问题一转换:给出1919个范围 [ a i , b i ] [a_i,b_i] [ai,bi],问最少取多少个点使得每个范围内至少有一个点
vector<pair<int,int>>v(1919);
void solve(){double a[N],b[N];for(int i=1;i<=1919;i++){a[i] = 2+weight[i];b[i] = min({2.0*weight[i],sqrt(weight[i]*weight[i] + height[i]*height[i]), sqrt(weight[i]*weight[i] + length[i]*length[i])});if((long long)b[i] == b[i])b[i]--;b[i] = (int)b[i];v[i-1].first = a[i] , v[i-1].second=b[i];}
}
void solve2(){//贪心 每次未放入取上限最小的上限sort(v.begin(),v.end(),[&](pair<int,int> x, pair<int,int> y){if(x.first == y.first)return x.second < y.second;return x.first < y.first;});int cnt = 0 , start=0 , end;vector<pair<int,int>>ans;while(cnt < 1919){double x = v[start].second;cnt++;bool flag = false;for(int i=start;i<v.size();i++){if(v[i].first>x){end = i-1;flag = true;break;}}if(flag)ans.push_back(make_pair(v[end].first,x));else{ans.push_back(make_pair(v[v.size()-1].first,x));break;}start = end+1;}cout << cnt << '\n';//答案 4 个for(auto x:ans){cout << x.first << ',' << x.second << '\n';}
}
问题二转换:给出1919个范围 [ a i , b i ] [a_i,b_i] [ai,bi],给出最少取多少个点使得每个范围内至少有一个点,求全部可能取值
注:不知道最小值为4,当新题做
vector<int>ans2;
int now_ans = 47;
int k=0;//不同取值种类数
int main() {solve();sort(v.begin(),v.end(),[&](pair<int,int> x, pair<int,int> y){if(x.first == y.first)return x.second < y.second;return x.first < y.first;});solve2_f(0,1);cout << k;return 0;
}
void solve2_f(int start , int cnt){if(cnt > now_ans)return ;for(int i = v[start].second;i>=v[start].first;i--){bool flag = false;for(int j=start;j<v.size();j++){if(v[j].first>i){flag = true;ans2.push_back(i);solve2_f(j,cnt+1);ans2.pop_back();break;}}if(!flag){ans2.push_back(i);for(auto x:ans2)cout << x << ' ';cout << '\n';ans2.pop_back();now_ans = min(now_ans,cnt);}}
}
问题二
纯编程求解:
在上一个问题基础上加个冗余计算即可
void solve2_f(int start , int cnt ,int rong){if(cnt > now_ans)return ;for(int i = v[start].second;i>=v[start].first;i--){bool flag = false;int sum = 0;for(int j=start;j<v.size();j++){if(v[j].first>i){flag = true;ans2.push_back(i);solve2_f(j,cnt+1,rong + sum);ans2.pop_back();break;}sum += i-v[j].first;}if(!flag){k++;ans2.push_back(i);for(auto x:ans2)cout << x << ' ';cout << "rong:" << rong;cout << '\n';ans2.pop_back();now_ans = min(now_ans,cnt);}}
}
求解得到最小的有
19 33 44 60 rong:10875
19 33 44 59 rong:10875
19 33 44 58 rong:10875
答案为19,33,44,58
因为最后一个取值没有计算冗余度,明显取58时候冗余度是最少的