一、部分题目
2014高教社杯全国大学生数学建模竞赛题目
D题 储药柜的设计
储药柜的结构类似于书橱,通常由若干个横向隔板和竖向隔板将储药柜分割成若干个储药槽(如图1所示)。为保证药品分拣的准确率,防止发药错误,一个储药槽内只能摆放同一种药品。药品在储药槽中的排列方式如图2所示。药品从后端放入,从前端取出。一个实际储药柜中药品的摆放情况如图3所示。
为保证药品在储药槽内顺利出入,要求药盒与两侧竖向隔板之间、与上下两层横向隔板之间应留2mm的间隙,同时还要求药盒在储药槽内推送过程中不会出现并排重叠、侧翻或水平旋转。在忽略横向和竖向隔板厚度的情况下,建立数学模型,给出下面几个问题的解决方案。
问题1 药房内的盒装药品种类繁多,药盒尺寸规格差异较大,附件1中给出了一些药盒的规格。请利用附件1的数据,给出竖向隔板间距类型最少的储药柜设计方案,包括类型的数量和每种类型所对应的药盒规格。
问题2 药盒与两侧竖向隔板之间的间隙超出2mm的部分可视为宽度冗余。增加竖向隔板的间距类型数量可以有效地减少宽度冗余,但会增加储药柜的加工成本,同时降低了储药槽的适应能力。设计时希望总宽度冗余尽可能小,同时也希望间距的类型数量尽可能少。仍利用附件1的数据,给出合理的竖向隔板间距类型的数量以及每种类型对应的药品编号。
问题3 考虑补药的便利性,储药柜的宽度不超过2.5m、高度不超过2m,传送装置占用的高度为0.5m,即储药柜的最大允许有效高度为1.5m。药盒与两层横向隔板之间的间隙超出2mm的部分可视为高度冗余,平面冗余=高度冗余×宽度冗余。在问题2计算结果的基础上,确定储药柜横向隔板间距的类型数量,使得储药柜的总平面冗余量尽可能地小,且横向隔板间距的类型数量也尽可能地少。
问题4 附件2给出了每一种药品编号对应的最大日需求量。在储药槽的长度为1.5m、每天仅集中补药一次的情况下,请计算每一种药品需要的储药槽个数。为保证药房储药满足需求,根据问题3中单个储药柜的规格,计算最少需要多少个储药柜。
二、部分论文
三、部分源代码
问题1
% 完整代码 https://github.com/yan-fanyu/CUMCM-Paper-And-SourceCode
load xinghao.txt
N=size(xinghao);
data=zeros(N(1),5);
for i=1:N(1)
data(i,1)= xinghao(i,1);
data(i,2)= xinghao(i,2);
data(i,3)= xinghao(i,3);
data(i,4)= ceil(sqrt(xinghao(i,2)^2+xinghao(i,3)^2));
data(i,5)= ceil(sqrt(xinghao(i,1)^2+xinghao(i,3)^2));
end
K_min=min(xinghao(:,3));
K_max=max(xinghao(:,3));
C_min=K_min;
C_K=2*C_min-1;
C_max=C_K-4;
while(C_max<K_max)
index=[];
data_temp=[];
for i=1:N(1)
if (data(i,3)<=C_max) && (data(i,3)>=C_min)
index=[index i];
data_temp=[data_temp;data(i,4:5)];
end
end
DJ=min(min(data_temp()));
if (C_K > DJ)
C_K=DJ-1;
C_max=C_K-4;
else
index%输出药槽宽度对应的药盒编号
num=size(index) %输出药槽宽度对应药盒的数量
C_K %输出药槽宽度
%计算宽度冗余
rongyu=0;
for k=1:num(2)
if ( (C_K-data(index(k),3))>4 )
rongyu=rongyu+(C_K-data(index(k),3)-4);
end
end
rongyu
C_min=C_max+1;
C_K=2*C_min-1;
if(C_K>56+4)
C_K=60;
C_max=56;
index=[];
data_temp=[];
for i=1:N(1)
if (data(i,3)<=C_max) && (data(i,3)>=C_min)
index=[index i];
data_temp=[data_temp;data(i,4:5)];
end
end
DJ=min(min(data_temp()));
if (C_K > DJ)
C_K=DJ-1;
C_max=C_K-4;
else
index%输出药槽宽度对应的药盒编号
num=size(index) %输出药槽宽度对应药盒的数量
C_K %输出药槽宽度
%计算宽度冗余
rongyu=0;
for k=1:num(2)
if ( (C_K-data(index(k),3))>4 )
rongyu=rongyu+(C_K-data(index(k),3)-4);
end
end
rongyu
end
else
C_max=C_K-4;
end
end
end
问题2
% 完整代码 https://github.com/yan-fanyu/CUMCM-Paper-And-SourceCode
fid=fopen('F:\数学建模\2014\D\index.txt','w');
fclose(fid);
load xinghao.txt
N=size(xinghao);
data=zeros(N(1),5);
data_CK=zeros(N(1),2);%保存每种药品的储药槽宽
for i=1:N(1)
data(i,1)= xinghao(i,1);
data(i,2)= xinghao(i,2);
data(i,3)= xinghao(i,3);
data(i,4)= ceil(sqrt(xinghao(i,2)^2+xinghao(i,3)^2));%高宽对角线
data(i,5)= ceil(sqrt(xinghao(i,1)^2+xinghao(i,3)^2));%长宽对角线
end
K_min=min(xinghao(:,3));
K_max=max(xinghao(:,3));
sum_rongyu=0;
C_K=[19 31 39 50 60]
% C_min=(C_K(1)+1)/2;
% C_max=C_K(1)-4;
% index=[];
% for i=1:N(1)
% if (data(i,3)<=C_max) && (data(i,3)>=C_min)
% index=[index i];
% end
% end
% % index%输出药槽宽度对应的药盒编号
% num=size(index) %输出药槽宽度对应药盒的数量
% C_K(1) %输出药槽宽度
% %计算宽度冗余
% rongyu=0;
% for k=1:num(2)
% if ( (C_K(1)-data(index(k),3))>4 )
% rongyu=rongyu+(C_K(1)-data(index(k),3));
% end
% end
% rongyu
% sum_rongyu=sum_rongyu+rongyu;
num_C=5;
j=1;
while( j<=num_C)
if(j==1)
C_min=K_min;
else
C_min=C_max+1;
end
C_max=C_K(j)-4;
index=[];
for i=1:N(1)
if (data(i,3)<=C_max) && (data(i,3)>=C_min)
index=[index i];
end
end
% index%输出药槽宽度对应的药盒编号
num=size(index) %输出药槽宽度对应药盒的数量
C_K(j) %输出药槽宽度
%计算宽度冗余
rongyu=0;
for k=1:num(2)
if ( (C_K(j)-data(index(k),3))>4 )
rongyu=rongyu+(C_K(j)-data(index(k),3)-4);
end
end
rongyu
%分裂为2,均分
temp=floor((C_max-C_min)/2);
C_min_1=C_min;
C_max_1=C_min_1+temp;
C_K_1=C_max_1+4;
C_min_2=C_max_1+1;
C_max_2=C_max;
C_K_2=C_max_2+4;
index_1=[];
for i=1:N(1)
if (data(i,3)<=C_max_1) && (data(i,3)>=C_min_1)
index_1=[index_1 i];
end
end
% index_1%输出药槽宽度对应的药盒编号
num=size(index_1) %输出药槽宽度对应药盒的数量
C_K_1 %输出药槽宽度
%计算宽度冗余
rongyu_1=0;
for k=1:num(2)
if ( (C_K_1-data(index_1(k),3))>4 )
rongyu_1=rongyu_1+(C_K_1-data(index_1(k),3)-4);
end
end
rongyu_1
index_2=[];
for i=1:N(1)
if (data(i,3)<=C_max_2) && (data(i,3)>=C_min_2)
index_2=[index_2 i];
end
end
% index_1%输出药槽宽度对应的药盒编号
num=size(index_2) %输出药槽宽度对应药盒的数量
C_K_2 %输出药槽宽度
%计算宽度冗余
rongyu_2=0;
for k=1:num(2)
if ( (C_K_2-data(index_2(k),3))>4 )
rongyu_2=rongyu_2+(C_K_2-data(index_2(k),3)-4);
end
end
rongyu_2
%计算总冗余
sum_rongyu=0;
num_CC=size(C_K);
for p=1:num_CC(2)
if(p==1)
C_min_S=K_min;
else
C_min_S=C_max_S+1;
end
C_max_S=C_K(p)-4;
index=[];
for i=1:N(1)
if (data(i,3)<=C_max_S) && (data(i,3)>=C_min_S)
index=[index i];
end
end
% index%输出药槽宽度对应的药盒编号
num=size(index) %输出药槽宽度对应药盒的数量
C_K(p) %输出药槽宽度
%计算宽度冗余
rongyu_t=0;
for k=1:num(2)
if ( (C_K(p)-data(index(k),3))>4 )
rongyu_t=rongyu_t+(C_K(p)-data(index(k),3)-4);
end
end
sum_rongyu=sum_rongyu+rongyu_t;%总冗余
end
dec_rongyu=rongyu-(rongyu_1+rongyu_2);
if (dec_rongyu/sum_rongyu)>0.07%冗余降低超过10%,保持分裂
C_K=[C_K(1:j-1) C_K_1 C_K(j:num_C)]
num_C=num_C+1;
j=j-1;
if(j>=1)
C_max=C_K(j)-4;
end
end
j=j+1;
end
%分裂完成,计算总冗余
sum_rongyu=0;
num_C=size(C_K);
for j=1:num_C(2)
if(j==1)
C_min=K_min;
else
C_min=C_max+1;
end
C_max=C_K(j)-4;
index=[];
for i=1:N(1)
if (data(i,3)<=C_max) && (data(i,3)>=C_min)
index=[index i];
end
end
% index%输出药槽宽度对应的药盒编号
num=size(index) %输出药槽宽度对应药盒的数量
C_K(j) %输出药槽宽度
fid=fopen('F:\数学建模\2014\D\index.txt','a');
fprintf(fid,'%d ',index);
fprintf(fid,'\n');
fclose(fid);
%计算宽度冗余
rongyu=0;
for k=1:num(2)
if ( (C_K(j)-data(index(k),3))>4 )
rongyu=rongyu+(C_K(j)-data(index(k),3)-4);
end
end
rongyu
sum_rongyu=sum_rongyu+rongyu;
%保存每种药品的储药槽宽
for k=1:num(2)
data_CK(index(k),1)=C_K(j);
end
end
sum_rongyu
save data_CK;%保存每种药品的储药槽宽
问题3
% 完整代码 https://github.com/yan-fanyu/CUMCM-Paper-And-SourceCode
load xinghao.txt
load data_CK
N=size(xinghao);
data=zeros(N(1),5);
for i=1:N(1)
data(i,1)= xinghao(i,1);
data(i,2)= xinghao(i,2);
data(i,3)= xinghao(i,3);
data(i,4)= ceil(sqrt(xinghao(i,2)^2+xinghao(i,3)^2));%高宽对角线
data(i,5)= ceil(sqrt(xinghao(i,1)^2+xinghao(i,2)^2));%长高对角线
end
Kg_min=min(xinghao(:,2));
Kg_max=max(xinghao(:,2));
sum_rongyu=0;
C_G=[53 72 104 129];
num_C=4;
j=1;
while( j<=num_C)
if(j==1)
Cg_min=Kg_min;
else
Cg_min=Cg_max+1;
end
Cg_max=C_G(j)-4;
index=[];
for i=1:N(1)
if (data(i,2)<=Cg_max) && (data(i,2)>=Cg_min)
index=[index i];
end
end
% index%输出药槽宽度对应的药盒编号
num=size(index) %输出药槽宽度对应药盒的数量
C_G(j) %输出药槽高度
%计算平面冗余
rongyu=0;
for k=1:num(2)
if ( (C_G(j)-data(index(k),2))>4 ) && ( (data_CK(index(k),1)-data(index(k),3))>4 )
rongyu=rongyu+(C_G(j)-data(index(k),2)-4)*(data_CK(index(k),1)-data(index(k),3)-4);
end
end
rongyu
%分裂为2,均分
temp=floor((Cg_max-Cg_min)/2);
Cg_min_1=Cg_min;
Cg_max_1=Cg_min_1+temp;
C_G_1=Cg_max_1+4;
Cg_min_2=Cg_max_1+1;
Cg_max_2=Cg_max;
C_G_2=Cg_max_2+4;
index_1=[];
for i=1:N(1)
if (data(i,2)<=Cg_max_1) && (data(i,2)>=Cg_min_1)
index_1=[index_1 i];
end
end
% index_1%输出药槽宽度对应的药盒编号
num=size(index_1) %输出药槽宽度对应药盒的数量
C_G_1 %输出药槽宽度
%计算平面冗余
rongyu_1=0;
for k=1:num(2)
if ( (C_G_1-data(index_1(k),2))>4 ) && ( (data_CK(index_1(k),1)-data(index_1(k),3))>4 )
rongyu_1=rongyu_1+(C_G_1-data(index_1(k),2)-4)*(data_CK(index_1(k),1)-data(index_1(k),3)-4);
end
end
rongyu_1
index_2=[];
for i=1:N(1)
if (data(i,2)<=Cg_max_2) && (data(i,2)>=Cg_min_2)
index_2=[index_2 i];
end
end
% index_1%输出药槽宽度对应的药盒编号
num=size(index_2) %输出药槽宽度对应药盒的数量
C_G_2 %输出药槽高度
%计算平面冗余
rongyu_2=0;
for k=1:num(2)
if ( (C_G_2-data(index_2(k),2))>4 )&& ( (data_CK(index_2(k),1)-data(index_2(k),3))>4 )
rongyu_2=rongyu_2+(C_G_2-data(index_2(k),2)-4)*(data_CK(index_2(k),1)-data(index_2(k),3)-4);
end
end
rongyu_2
%计算总冗余
sum_rongyu=0;
num_CC=size(C_G);
for p=1:num_CC(2)
if(p==1)
Cg_min_S=Kg_min;
else
Cg_min_S=Cg_max_S+1;
end
Cg_max_S=C_G(p)-4;
index=[];
for i=1:N(1)
if (data(i,2)<=Cg_max_S) && (data(i,2)>=Cg_min_S)
index=[index i];
end
end
% index%输出药槽宽度对应的药盒编号
num=size(index) %输出药槽宽度对应药盒的数量
C_G(p) %输出药槽宽度
%计算平面冗余
rongyu_t=0;
for k=1:num(2)
if ( (C_G(p)-data(index(k),2))>4 )&& ( (data_CK(index(k),1)-data(index(k),3))>4 )
rongyu_t=rongyu_t+(C_G(p)-data(index(k),2)-4)*(data_CK(index(k),1)-data(index(k),3)-4);
end
end
sum_rongyu=sum_rongyu+rongyu_t;%总冗余
end
dec_rongyu=rongyu-(rongyu_1+rongyu_2);
if (dec_rongyu/sum_rongyu)>0.04%冗余降低超过10%,保持分裂
C_G=[C_G(1:j-1) C_G_1 C_G(j:num_C)]
num_C=num_C+1;
j=j-1;
if(j>=1)
Cg_max=C_G(j)-4;
end
end
j=j+1;
end
%分裂完成,计算总冗余
sum_rongyu=0;
num_C=size(C_G);
for j=1:num_C(2)
if(j==1)
Cg_min=Kg_min;
else
Cg_min=Cg_max+1;
end
Cg_max=C_G(j)-4;
index=[];
for i=1:N(1)
if (data(i,2)<=Cg_max) && (data(i,2)>=Cg_min)
index=[index i];
end
end
% index%输出药槽宽度对应的药盒编号
num=size(index) %输出药槽宽度对应药盒的数量
C_G(j) %输出药槽宽度
%计算宽度冗余
rongyu=0;
for k=1:num(2)
if ( (C_G(j)-data(index(k),2))>4 )&& ( (data_CK(index(k),1)-data(index(k),3))>4 )
rongyu=rongyu+(C_G(j)-data(index(k),2)-4)*(data_CK(index(k),1)-data(index(k),3)-4);
end
end
rongyu
sum_rongyu=sum_rongyu+rongyu;
%保存每种药品的储药槽高
for k=1:num(2)
data_CG(index(k),1)=C_G(j);
end
end
sum_rongyu
save data_CG;%保存每种药品的储药槽宽
问题4
% 完整代码 https://github.com/yan-fanyu/CUMCM-Paper-And-SourceCode
load xinghao.txt
load data_CK%每种药的储药槽宽 12类
load data_CG%每种药的储药槽高 13类
N=size(xinghao);
data=zeros(N(1),5);
C_number=zeros(N(1),1);
num_Yaogui=1;
% *******************************
for i=1:N(1)
data(i,1)= xinghao(i,1);%长
data(i,2)= xinghao(i,2);%高
data(i,3)= xinghao(i,3);%宽
data(i,4)= ceil(sqrt(xinghao(i,2)^2+xinghao(i,3)^2));%高宽对角线
data(i,5)= ceil(sqrt(xinghao(i,1)^2+xinghao(i,3)^2));%长宽对角线
end
load liang.txt
for i=1:N(1)
n=floor(1500/data(i,1));%长
C_number(i)=ceil(liang(i)/n);%每种药品的药槽数量
end
%需求量大的药优先摆放,同一种药的药槽放在一起(同一行相邻摆放),同样高的药槽放在同一行
sum_CK=zeros(N(1),1);
for i=1:N(1)
sum_CK(i)=data_CK(i)*C_number(i);%编号i的药的药槽总宽
end
index_already=[];
i=1;
num_already=0;
CG_all=0;%计算药槽高度累加
CG_sum=0;%计算所有药槽累计的总高度
while( num_already<N(1) )%从最小编号的药开始(编号越小需求量越大)
index_sameline=[];
index_sameline=[index_sameline i];
sum_long=0;
num_line=1;
if sum_CK(i)<2500%储药柜宽度为2500mm
sum_long=sum_CK(i);
CG_temp=data_CG(i);
data_CG(i)=0;
for j=2:N(1)
if CG_temp==data_CG(j);%寻找相同槽高的最小编号的药(最小编号的药需求量最大)
sum_long=sum_long+sum_CK(j);
if sum_long<=2500%储药柜宽度为2500mm
index_sameline=[index_sameline j];
num_line=num_line+1;%这一行增加一种药
data_CG(j)=0;%清除为0,不参与下一次摆放
else
sum_long=sum_long-sum_CK(j);
end
end
end
end
index_sameline %输出一行药的编号
CG_temp%输出一行的高度
index_already=[index_already index_sameline];
num_already=size(index_already);
data_CG(i)=0;%清除为0,不参与下一次摆放;
k=1;
while(k<num_already(2))
for k=1:num_already(2)
if i==index_already(k)
i=i+1;
break;
end
end
end
CG_sum=CG_sum+CG_temp;
CG_all=CG_all+CG_temp;
if CG_all>1500%储药柜有效高度为1500mm
CG_all=CG_temp;
num_Yaogui=num_Yaogui+1;
end
if CG_all==1500
CG_all=0;
num_Yaogui=num_Yaogui+1;
end
end
CG_sum%输出药槽摆放后的总高度
num_Yaogui%输出储药柜数量