2021年mathorcupD题,钢材切割下料问题,按照一位比赛组程序有一个函数无法还原。遇到的现象和发生背景
function Question1_Prepare()
%% 数据的导入与预定义
product = xlsread('原料', 'sheet2', 'B2 : G16'); % 长度、宽度、需求量、浮动比例、种类
material = xlsread('原料', 'sheet1', 'B2 : E11'); % 长度、宽度、库存
PLAN = cell(10, 6); % 存放计划切割方案的元组
plan = zeros(10, 10); %
%% 二维矩形的排样
for j = 1 : 10 % 对十种原料进行遍历
% 对长进行循环
if(material(j, 1) > min(product(1 : 5, 1))) % 如果原料的长>卷料订单中长的最小值
i_list = find(product(1 : 5, 1) < material(j, 1)); % 保存满足放置条件的订单的位置
ws1 = material(j, 2); % 原料剩余可用的宽度
lsl = material(j, 1); % 原料剩余可用的长度
num_kind_width = zeros(1, 5); % 5种订单宽的切割方案
num_kind_length = zeros(1, 5); % 5种订单长的切割方案
% 对宽进行循环
while (ws1 > min(product(1 : 5, 2))) % 当原料剩余可用的宽度 > 卷料订单中宽的最小值
i= randchoose(i_list,1); % 随机从满足放置条件的订单中选一个
if (ws1 - product(i, 2)) < 0 % 如果在放置后剩余可用的宽度仍大于零则继续
continue
end
% 当某一个节点之后卷料剩余可用宽度小于零执行以下内容
ws1 = ws1 - product(i, 2); % 更新原料剩余可用宽度
num_kind_width(i) = num_kind_width(i) + 1; % 更新原料剩余可用长度
num_kind_length(i) = fix(material(j, 1) / product(i, 1)); % 计算长上放置的订单数量
% num_kind_width_length存放格式:1~5:五种订单宽的数量,6~10:五种订单长的数量
num_kind_width_length = [num_kind_width, num_kind_length]; % 每种原料中长、宽放置的订单数量
end
% 将第j种原料的五种订单的各个数量存放进plan数组
% plan存放格式:第j行:第几种原料,每一行后面的10个数:第几种原料放置各个订单的长和宽的数量
for k = 1 : 10
plan(j, k) = num_kind_width_length(k);
end
ws2 = material(j, 1) - max(plan(j, 6 : 10) .* product(1 : 5, 1)'); % max()求得原料切割订单后与余料的一个切面
ls2 = material(j, 2); % 原料的宽度
lsl = lsl - ws2;
% 长度余量
S_Product = 0;
for n = 1 : 5
S_Product = S_Product + plan(j,n) * plan(j,n + 5) * product(n,6);
end
% 以下为原题中判断余料是否满足标准的条件设置,可以根据题意进行更改
S_surplus = 0;
if(ws1 > 100 && lsl > 50000)
S_surplus = S_surplus + ws1 * lsl;
end
if(ws2 > 2000 && ls2 > 1000)
S_surplus = S_surplus + ws2 * ls2;
end
R = (S_surplus + S_Product) / material(j, 4);
% 数据的输出
PLAN{j, 6} = R;
for n = 1 : 5
PLAN{j, n} = [num_kind_width_length(n), num_kind_width_length(n + 5)];
end
end
end
end
Question1_Prepare
错误使用 randchoose
输出参数太多。
出错 Question1_Prepare (第 19 行)
i= randchoose(i_list,1); % 随机从满足放置条件的订单中选一个
randchoose()函数无法随机选择,我也不会定义。运行结果及报错内容
达到随机选择订单的效果 我想要达到的结果
修改代码
//主程序部分
for (; T > 10; T*=0.96)
{
tuihuo(productbuf, material, alproduct, T, ExceStock);//迭代一步
cout << ExceStock << " " << endl;
if (ExceStock <= 0.01)break;
}
//退火算法部分
void tuihuo(deque<stock> &probuf, const stock &matrl, vector<stock> &alpro, double &T, double &excestock)
{
deque<stock> probuf1(probuf);//放置交换后的一个邻域
vector<stock> alpro1; //放置交换后的解启发式运算结果
twoOpt(probuf, probuf1);
double exstock, exstock1;//余料率
alpro.clear();
exstock = ProductLayout(probuf, matrl, alpro);
exstock1 = ProductLayout(probuf1, matrl, alpro1);
if (exstock1 <= exstock)//如果邻域更好
{
probuf.swap(probuf1);
exstock = exstock1;
alpro = alpro1;
}
else
{
double P = exp((exstock - exstock1)/T);//概率
static default_random_engine e1;
static uniform_int_distribution<unsigned> u1(0, 1);
if (P > u1(e1))
{
probuf.swap(probuf1);
exstock = exstock1;
alpro = alpro1;
}
}
excestock = exstock;
}