Early Orders

本文介绍了一种使用贪心策略和单调栈技巧解决早期订单问题的方法。通过遍历输入数组,当栈顶元素大于待插入元素且该元素未出现时,弹出栈顶并标记。最后输出按顺序处理后的订单序列。

Early Orders

思路

贪心+单调栈
主要思想:可以看出,当栈顶元素要大于待入队元素时,看是否该栈顶元素后面是否还存在该数,有则将栈顶元素弹出。

代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>

using namespace std;

const int N = 200010;

stack<int> S;
int cnt[N];
int a[N];
int n, m;
bool st[N];
int ans[N];

int main() {
    scanf("%d%d", &n, &m);
    for(int i = 0; i < n; i ++) {
        scanf("%d", &a[i]);
        cnt[a[i]] ++;
    }
    
    S.push(a[0]);
    st[a[0]] = true;
    cnt[a[0]] --;
    for(int i = 1; i < n; i ++) {
        cnt[a[i]] --;
        while(S.size() && (a[i] < S.top()) && !st[a[i]] && (cnt[S.top()] > 0)) {
            st[S.top()] = false;
            S.pop();
        }
        if(!st[a[i]]) {
            S.push(a[i]);
            st[a[i]] = true;
        }
    }
    
    int num = 0;
    
    while(!S.empty()) {
        int t = S.top();
        ans[num ++] = t;
        S.pop();
    }
    for(int i = num - 1; i >= 0; i --)
        printf("%d ", ans[i]);
    return 0;
}
function [schedule_table, best_metrics] = GA_schedule() clc; % 初始化py库 obj = py.importlib.import_module(‘bj’); py.importlib.reload(obj); % 获取数据 orders_df = py.bj.fetch_orders(); production_lines_df = py.bj.fetch_production_lines(); % 转换函数 to_double = @(x) cellfun(@(v) double(py.float(v)), cell(py.list(x)), ‘UniformOutput’, false); to_str = @(x) cellfun(@char, cell(py.list(x)), ‘UniformOutput’, false); % 订单数据处理 order_ids = to_double(py.getattr(orders_df, ‘ORDER_ID’)); order_dates = datetime(to_str(py.getattr(orders_df, ‘ORDER_DATE’))); due_dates = datetime(to_str(py.getattr(orders_df, ‘DUE_DATE’))); product_ids = to_double(py.getattr(orders_df, ‘PRODUCT_ID’)); product_names = to_str(py.getattr(orders_df, ‘PRODUCT_NAME’)); product_spec = to_str(py.getattr(orders_df, ‘SPECIFICATION_INFO’)); order_quantities = to_double(py.getattr(orders_df, ‘ORDER_QUANTITY’)); outstanding_quantities = to_double(py.getattr(orders_df, ‘OUTSTANDING_QUANTITY’)); % 产线数据处理(LINE_ID 改为字符串) line_names = to_str(py.getattr(production_lines_df, ‘LINE_NAME’)); line_ids = to_str(py.getattr(production_lines_df, ‘LINE_ID’)); line_rates = to_double(py.getattr(production_lines_df, ‘LINE_RATE’)); yield_rates = to_double(py.getattr(production_lines_df, ‘YIELD_RATE’)); status = to_str(py.getattr(production_lines_df, ‘STATUS’)); production_ids = to_double(py.getattr(production_lines_df, ‘PRODUCT_ID’)); % 构建订单结构体 num_orders = length(order_ids); orders = struct([]); for i = 1:num_orders orders(i).OrderID = order_ids{i}; orders(i).OrderDate = order_dates(i); orders(i).DueDate = due_dates(i); orders(i).ProductID = product_ids{i}; orders(i).ProductName = product_names{i}; orders(i).Specification = product_spec{i}; orders(i).OrderQuantity = order_quantities{i}; orders(i).OutstandingQuantity = outstanding_quantities{i}; end % 构建产线结构体 num_lines = length(line_ids); productions = struct([]); for j = 1:num_lines productions(j).LineID = line_ids{j}; productions(j).LineName = line_names{j}; productions(j).LineRate = line_rates{j}; productions(j).YieldRate = yield_rates{j} / 100; productions(j).Status = status{j}; productions(j).ProductID = production_ids{j}; end % GA参数 ga_params.pop_size = 60; ga_params.max_gen = 200; ga_params.crossover_rate = 0.8; ga_params.mutation_rate = 0.25; ga_params.tournament_k = 3; % 基准时间 all_order_dates = [orders.OrderDate]; baseline_start = min(all_order_dates); line_id_to_index = containers.Map(); for j = 1:num_lines line_id_to_index(productions(j).LineID) = j; end % 兼容产线:仍用索引存储 compatible_lines = cell(num_orders, 1); for i = 1:num_orders pid = orders(i).ProductID; idxs = []; for j = 1:num_lines if isequal(productions(j).ProductID, pid) && strcmpi(productions(j).Status, ‘正常’) idxs(end+1) = j; end end compatible_lines{i} = idxs; end % 加工时间计算函数 calc_proc_duration = @(qty, rate, yield) hours(qty ./ (rate .* yield)); % 主模拟函数 function [schedule, metrics] = simulate_schedule(orders, productions, seq, assign, … compatible_lines, calc_proc_duration, baseline_start, line_id_to_index) num_orders_local = length(seq); num_productions = length(productions); line_available = repmat(baseline_start, num_productions, 1); schedule = repmat(struct(), num_orders_local, 1); total_late_hours = 0; latest_finish = baseline_start; penalty_unassigned = 0; for k = 1:num_orders_local i = seq(k); schedule(k).Seq = k; schedule(k).OrderID = orders(i).OrderID; schedule(k).OrderDate = orders(i).OrderDate; schedule(k).DueDate = orders(i).DueDate; schedule(k).ProductID = orders(i).ProductID; schedule(k).ProductName = orders(i).ProductName; schedule(k).Specification = orders(i).Specification; schedule(k).OrderQuantity = orders(i).OrderQuantity; schedule(k).OutstandingQuantity = orders(i).OutstandingQuantity; assigned_line_id = assign{i}; if isempty(assigned_line_id) || ~isKey(line_id_to_index, assigned_line_id) schedule(k).AssignedLineID = "待确认"; schedule(k).AssignedLineName = "待确认"; schedule(k).StartTime = NaT; schedule(k).EndTime = NaT; schedule(k).ProcDuration = duration(0,0,0); penalty_unassigned = penalty_unassigned + 1e6; continue; end j = line_id_to_index(assigned_line_id); % 转为索引 % 检查是否兼容 cl = compatible_lines{i}; if ~ismember(j, cl) schedule(k).AssignedLineID = string(assigned_line_id); schedule(k).AssignedLineName = productions(j).LineName; schedule(k).StartTime = NaT; schedule(k).EndTime = NaT; schedule(k).ProcDuration = duration(0,0,0); penalty_unassigned = penalty_unassigned + 1e5; continue; end qty = double(orders(i).OutstandingQuantity); rate = double(productions(j).LineRate); yld = double(productions(j).YieldRate); if rate <= 0 || yld <= 0 proc_dur = hours(1e6); else proc_dur = calc_proc_duration(qty, rate, yld); end est_start = max(line_available(j), orders(i).OrderDate); est_end = est_start + proc_dur; line_available(j) = est_end; schedule(k).AssignedLineID = string(assigned_line_id); schedule(k).AssignedLineName = string(productions(j).LineName); schedule(k).StartTime = est_start; schedule(k).EndTime = est_end; schedule(k).ProcDuration = proc_dur; late_h = max(0, hours(est_end - orders(i).DueDate)); total_late_hours = total_late_hours + late_h; if est_end > latest_finish latest_finish = est_end; end end metrics.total_late_hours = total_late_hours; metrics.latest_finish = latest_finish; metrics.penalty_unassigned = penalty_unassigned; end % 初始化种群 population(ga_params.pop_size) = struct(); for p = 1:ga_params.pop_size seq = randperm(num_orders); assign = cell(num_orders, 1); for i = 1:num_orders cl = compatible_lines{i}; if ~isempty(cl) selected_idx = cl(randi(length(cl))); assign{i} = productions(selected_idx).LineID; % 存字符串 else assign{i} = ''; end end population(p).seq = seq; population(p).assign = assign; [~, metrics] = simulate_schedule(orders, productions, seq, assign, ... compatible_lines, calc_proc_duration, baseline_start, line_id_to_index); finish_hours = hours(metrics.latest_finish - baseline_start); population(p).fitness = metrics.total_late_hours + 0.0001*finish_hours + metrics.penalty_unassigned; end % 主循环 best_history = nan(ga_params.max_gen, 1); for gen = 1:ga_params.max_gen newpop = population; [~, idxs_pop] = sort([population.fitness]); newpop(1) = population(idxs_pop(1)); for slot = 2:ga_params.pop_size p1 = tournament_select(population, ga_params.tournament_k); p2 = tournament_select(population, ga_params.tournament_k); p1_assign = p1.assign; p2_assign = p2.assign; child = p1; if rand < ga_params.crossover_rate child.seq = order_crossover(p1.seq, p2.seq); child.assign = assign_crossover(p1_assign, p2_assign); end if rand < ga_params.mutation_rate child.seq = swap_mutation(child.seq); end if rand < ga_params.mutation_rate child.assign = assignment_mutation(child.assign, compatible_lines, productions, line_id_to_index); end [~, metrics] = simulate_schedule(orders, productions, child.seq, child.assign, ... compatible_lines, calc_proc_duration, baseline_start, line_id_to_index); finish_hours = hours(metrics.latest_finish - baseline_start); child.fitness = metrics.total_late_hours + 0.0001*finish_hours + metrics.penalty_unassigned; newpop(slot) = child; end population = newpop; best_history(gen) = min([population.fitness]); end % 提取最优解 [~, idxs] = sort([population.fitness]); best_ind = population(idxs(1)); [best_schedule, best_metrics] = simulate_schedule(orders, productions, best_ind.seq, best_ind.assign, … compatible_lines, calc_proc_duration, baseline_start, line_id_to_index); % 转换为表格 n = length(best_schedule); Seq = zeros(n,1); OrderID = zeros(n,1); OrderDate = NaT(n,1); DueDate = NaT(n,1); ProductID = zeros(n,1); ProductName = strings(n,1); Specification = strings(n,1); OrderQuantity = zeros(n,1); OutstandingQuantity = zeros(n,1); AssignedLineID = strings(n,1); AssignedLineName = strings(n,1); StartTime = NaT(n,1); EndTime = NaT(n,1); ProcDuration = duration(zeros(n,1),0,0); for k = 1:n s = best_schedule(k); Seq(k) = s.Seq; OrderID(k) = s.OrderID; OrderDate(k) = s.OrderDate; DueDate(k) = s.DueDate; ProductID(k) = s.ProductID; ProductName(k) = string(s.ProductName); Specification(k) = string(s.Specification); OrderQuantity(k) = s.OrderQuantity; OutstandingQuantity(k) = s.OutstandingQuantity; AssignedLineID(k) = string(s.AssignedLineID); AssignedLineName(k) = string(s.AssignedLineName); StartTime(k) = s.StartTime; EndTime(k) = s.EndTime; ProcDuration(k) = s.ProcDuration; end % 分离有效与无效调度 valid_idx = ~isnat(StartTime); invalid_idx = isnat(StartTime); valid_indices = find(valid_idx); invalid_indices = find(invalid_idx); [~, sort_idx_valid] = sort(StartTime(valid_idx)); [~, sort_idx_invalid] = sort(OrderDate(invalid_idx)); final_idx = [valid_indices(sort_idx_valid); invalid_indices(sort_idx_invalid)]; % 重排 Seq = (1:n)'; OrderID = OrderID(final_idx); OrderDate = OrderDate(final_idx); DueDate = DueDate(final_idx); ProductID = ProductID(final_idx); ProductName = ProductName(final_idx); Specification = Specification(final_idx); OrderQuantity = OrderQuantity(final_idx); OutstandingQuantity = OutstandingQuantity(final_idx); AssignedLineID = AssignedLineID(final_idx); AssignedLineName = AssignedLineName(final_idx); StartTime = StartTime(final_idx); EndTime = EndTime(final_idx); ProcDuration = ProcDuration(final_idx); % 输出表格 schedule_table = table(Seq, OrderID, OrderDate, DueDate, ProductID, ProductName, … Specification, OrderQuantity, OutstandingQuantity, AssignedLineID, … AssignedLineName, StartTime, EndTime, ProcDuration); % 设置时间格式 schedule_table.StartTime.Format = ‘yyyy-MM-dd HH:mm:ss’; schedule_table.EndTime.Format = ‘yyyy-MM-dd HH:mm:ss’; schedule_table.OrderDate.Format = ‘yyyy-MM-dd HH:mm:ss’; schedule_table.DueDate.Format = ‘yyyy-MM-dd HH:mm:ss’; % 导出 Excel if exist(‘schedule_table’, ‘var’) chinese_headers = {‘序号’,‘订单号’,‘订单日期’,‘订单交期’,‘产品编号’,‘产品名称’,‘产品规格’,… ‘订单数目’,‘未交数目’,‘分配产线编号’,‘分配产线名称’,‘预定开始时间’,… ‘预定结束时间’,‘预期消耗时长’}; output_dir = fullfile(pwd, 'downloads'); if ~exist(output_dir, 'dir'), mkdir(output_dir); end output_path = fullfile(output_dir, '排程结果.xlsx'); % 保持列数一致 if width(schedule_table) ~= numel(chinese_headers) warning('列数不匹配,自动对齐'); end schedule_table.Properties.VariableNames = chinese_headers(1:width(schedule_table)); writetable(schedule_table, output_path, 'FileType', 'spreadsheet'); disp(['排程结果已导出:', output_path]); else warning(‘无法导出 Excel’); end % 辅助函数 function p = tournament_select(pop, k) n = numel(pop); idx = randi(n, [k,1]); [~, bestidx] = min([pop(idx).fitness]); p = pop(idx(bestidx)); end function child_seq = order_crossover(a, b) n = length(a); p1 = sort(randi(n, [1,2])); seg = a(p1(1):p1(2)); rest = b(~ismember(b, seg)); child_seq = [rest(1:p1(1)-1), seg, rest(p1(1):end)]; end function child_assign = assign_crossover(a, b) n = length(a); cp = randi(n-1); child_assign = [a(1:cp); b(cp+1:end)]; end function s = swap_mutation(seq) n = length(seq); i = randi(n); j = randi(n); tmp = seq(i); seq(i) = seq(j); seq(j) = tmp; s = seq; end function asg = assignment_mutation(asg, compatible_lines, productions, line_id_to_index) n = length(asg); i = randi(n); cl = compatible_lines{i}; if ~isempty(cl) selected_idx = cl(randi(length(cl))); asg{i} = productions(selected_idx).LineID; else asg{i} = ‘’; end end end 这代码的排程能不能优化,大量数据计算太慢了
10-31
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值