匈牙利算法实现任务分配的MATLAB程序

1. 匈牙利算法核心实现

function [assignment, cost] = hungarian_algorithm(cost_matrix)
% 匈牙利算法实现任务分配
% 输入:
%   cost_matrix - n×n成本矩阵,cost_matrix(i,j)表示第i个工人完成第j项任务的成本
% 输出:
%   assignment - 分配结果,assignment(i)表示第i个工人分配的任务编号
%   cost - 总成本

    [n, m] = size(cost_matrix);
    
    % 确保是方阵
    if n ~= m
        error('成本矩阵必须是方阵');
    end
    
    % 步骤1: 复制成本矩阵
    cost_mat = cost_matrix;
    
    % 步骤2: 行缩减 - 每行减去该行的最小值
    for i = 1:n
        min_val = min(cost_mat(i, :));
        cost_mat(i, :) = cost_mat(i, :) - min_val;
    end
    
    % 步骤3: 列缩减 - 每列减去该列的最小值
    for j = 1:n
        min_val = min(cost_mat(:, j));
        cost_mat(:, j) = cost_mat(:, j) - min_val;
    end
    
    % 初始化分配结果
    assignment = zeros(1, n);
    covered_rows = false(1, n);
    covered_cols = false(1, n);
    
    max_iterations = 100;
    iteration = 0;
    
    while iteration < max_iterations
        iteration = iteration + 1;
        
        % 步骤4: 寻找初始分配
        [assignment, covered_rows, covered_cols] = find_assignment(cost_mat);
        
        % 如果找到了完整分配,退出循环
        if sum(assignment > 0) == n
            break;
        end
        
        % 步骤5: 覆盖所有零元素
        [covered_rows, covered_cols] = cover_zeros(cost_mat, covered_rows, covered_cols);
        
        % 步骤6: 调整矩阵
        cost_mat = adjust_matrix(cost_mat, covered_rows, covered_cols);
    end
    
    % 计算总成本
    cost = 0;
    for i = 1:n
        if assignment(i) > 0
            cost = cost + cost_matrix(i, assignment(i));
        end
    end
    
    if iteration >= max_iterations
        warning('匈牙利算法可能未收敛到最优解');
    end
end

function [assignment, covered_rows, covered_cols] = find_assignment(cost_mat)
% 在成本矩阵中寻找初始分配
    n = size(cost_mat, 1);
    assignment = zeros(1, n);
    covered_rows = false(1, n);
    covered_cols = false(1, n);
    
    % 寻找独立的零元素进行分配
    for i = 1:n
        for j = 1:n
            if cost_mat(i, j) == 0 && ~covered_rows(i) && ~covered_cols(j)
                assignment(i) = j;
                covered_rows(i) = true;
                covered_cols(j) = true;
                break;
            end
        end
    end
end

function [covered_rows, covered_cols] = cover_zeros(cost_mat, covered_rows, covered_cols)
% 用最少的线覆盖所有零元素
    n = size(cost_mat, 1);
    
    % 标记没有分配的行
    marked_rows = ~covered_rows;
    new_marked_rows = marked_rows;
    new_covered_cols = covered_cols;
    
    while true
        % 在标记的行中寻找零元素
        found_new = false;
        for i = find(new_marked_rows)
            for j = 1:n
                if cost_mat(i, j) == 0 && ~new_covered_cols(j)
                    new_covered_cols(j) = true;
                    found_new = true;
                end
            end
        end
        
        if ~found_new
            break;
        end
        
        % 更新标记的行
        new_marked_rows = false(1, n);
        for j = find(new_covered_cols)
            for i = 1:n
                if assignment_exists(cost_mat, i, j) && ~covered_rows(i)
                    new_marked_rows(i) = true;
                end
            end
        end
        
        covered_rows = covered_rows | new_marked_rows;
    end
    
    covered_cols = new_covered_cols;
end

function exists = assignment_exists(cost_mat, row, col)
% 检查是否存在分配
    exists = cost_mat(row, col) == 0;
end

function adjusted_mat = adjust_matrix(cost_mat, covered_rows, covered_cols)
% 调整成本矩阵
    n = size(cost_mat, 1);
    
    % 找到未被覆盖的最小元素
    min_val = inf;
    for i = 1:n
        for j = 1:n
            if ~covered_rows(i) && ~covered_cols(j) && cost_mat(i, j) < min_val
                min_val = cost_mat(i, j);
            end
        end
    end
    
    adjusted_mat = cost_mat;
    
    % 调整矩阵
    for i = 1:n
        for j = 1:n
            if ~covered_rows(i) && ~covered_cols(j)
                adjusted_mat(i, j) = adjusted_mat(i, j) - min_val;
            elseif covered_rows(i) && covered_cols(j)
                adjusted_mat(i, j) = adjusted_mat(i, j) + min_val;
            end
        end
    end
end

2. 完整的任务分配演示程序

function main_hungarian_demo()
% 匈牙利算法任务分配演示主程序

clc;
clear;
close all;

fprintf('=== 匈牙利算法任务分配演示 ===\n\n');

%% 生成示例数据
rng(42); % 设置随机种子保证可重复性

% 场景1: 5个工人分配5个任务
n_workers = 5;
n_tasks = 5;

% 生成随机成本矩阵 (1-20之间的整数)
cost_matrix = randi([1, 20], n_workers, n_tasks);

fprintf('成本矩阵:\n');
print_matrix(cost_matrix);
fprintf('\n');

%% 运行匈牙利算法
fprintf('运行匈牙利算法...\n');
tic;
[assignment, total_cost] = hungarian_algorithm(cost_matrix);
computation_time = toc;

fprintf('计算完成!耗时: %.4f 秒\n\n', computation_time);

%% 显示分配结果
display_assignment_results(cost_matrix, assignment, total_cost);

%% 可视化结果
visualize_assignment(cost_matrix, assignment);

%% 性能测试
fprintf('\n=== 性能测试 ===\n');
test_performance();

fprintf('\n=== 演示完成 ===\n');

end

function print_matrix(mat)
% 打印矩阵
    [n, m] = size(mat);
    for i = 1:n
        for j = 1:m
            fprintf('%3d ', mat(i, j));
        end
        fprintf('\n');
    end
end

function display_assignment_results(cost_matrix, assignment, total_cost)
% 显示分配结果
    n = length(assignment);
    
    fprintf('最优分配结果:\n');
    fprintf('工人\t任务\t成本\n');
    fprintf('----\t----\t----\n');
    
    for i = 1:n
        task = assignment(i);
        cost = cost_matrix(i, task);
        fprintf('%2d\t%2d\t%2d\n', i, task, cost);
    end
    
    fprintf('\n总成本: %d\n', total_cost);
    
    % 验证分配有效性
    assigned_tasks = unique(assignment);
    if length(assigned_tasks) == n && all(assigned_tasks > 0)
        fprintf('✓ 分配有效:每个任务都被分配且只分配一次\n');
    else
        fprintf('✗ 分配无效\n');
    end
end

function visualize_assignment(cost_matrix, assignment)
% 可视化分配结果
    figure('Position', [100, 100, 1200, 500]);
    
    % 子图1: 成本矩阵热图
    subplot(1, 2, 1);
    imagesc(cost_matrix);
    colorbar;
    title('成本矩阵热图', 'FontSize', 12, 'FontWeight', 'bold');
    xlabel('任务');
    ylabel('工人');
    
    % 标记分配位置
    [n, ~] = size(cost_matrix);
    hold on;
    for i = 1:n
        j = assignment(i);
        if j > 0
            plot(j, i, 'ro', 'MarkerSize', 10, 'LineWidth', 2);
            text(j, i, sprintf(' 工人%d', i), 'FontSize', 10, 'Color', 'red');
        end
    end
    hold off;
    
    % 添加数值标签
    for i = 1:n
        for j = 1:n
            text(j, i, num2str(cost_matrix(i, j)), ...
                'HorizontalAlignment', 'center', ...
                'FontWeight', 'bold', ...
                'Color', 'white');
        end
    end
    
    % 子图2: 分配关系图
    subplot(1, 2, 2);
    plot_assignment_graph(assignment, cost_matrix);
    
    sgtitle('匈牙利算法任务分配结果', 'FontSize', 14, 'FontWeight', 'bold');
end

function plot_assignment_graph(assignment, cost_matrix)
% 绘制分配关系图
    n = length(assignment);
    
    % 创建二分图
    workers_x = zeros(1, n);
    workers_y = linspace(1, 0, n);
    tasks_x = ones(1, n);
    tasks_y = linspace(1, 0, n);
    
    hold on;
    
    % 绘制工人节点
    for i = 1:n
        plot(workers_x(i), workers_y(i), 'bo', 'MarkerSize', 15, 'LineWidth', 2);
        text(workers_x(i) - 0.1, workers_y(i), sprintf('工人%d', i), ...
            'HorizontalAlignment', 'right', 'FontSize', 10);
    end
    
    % 绘制任务节点
    for j = 1:n
        plot(tasks_x(j), tasks_y(j), 'gs', 'MarkerSize', 15, 'LineWidth', 2);
        text(tasks_x(j) + 0.1, tasks_y(j), sprintf('任务%d', j), ...
            'HorizontalAlignment', 'left', 'FontSize', 10);
    end
    
    % 绘制分配边
    for i = 1:n
        task_j = assignment(i);
        if task_j > 0
            % 计算线的颜色基于成本(红色表示高成本,绿色表示低成本)
            cost = cost_matrix(i, task_j);
            max_cost = max(cost_matrix(:));
            color_intensity = cost / max_cost;
            line_color = [color_intensity, 0, 1 - color_intensity];
            
            plot([workers_x(i), tasks_x(task_j)], ...
                 [workers_y(i), tasks_y(task_j)], ...
                 'Color', line_color, 'LineWidth', 3);
            
            % 显示成本
            mid_x = (workers_x(i) + tasks_x(task_j)) / 2;
            mid_y = (workers_y(i) + tasks_y(task_j)) / 2;
            text(mid_x, mid_y, sprintf('成本:%d', cost), ...
                'BackgroundColor', 'white', 'FontSize', 9);
        end
    end
    
    xlim([-0.3, 1.3]);
    ylim([-0.1, 1.1]);
    title('任务分配关系图', 'FontSize', 12, 'FontWeight', 'bold');
    grid on;
    hold off;
end

function test_performance()
% 性能测试
    sizes = [10, 20, 50, 100];
    times = zeros(size(sizes));
    
    fprintf('性能测试:\n');
    fprintf('矩阵大小\t计算时间(秒)\n');
    fprintf('--------\t------------\n');
    
    for k = 1:length(sizes)
        n = sizes(k);
        test_matrix = randi([1, 100], n, n);
        
        tic;
        [assignment, cost] = hungarian_algorithm(test_matrix);
        times(k) = toc;
        
        fprintf('%d×%d\t\t%.4f\n', n, n, times(k));
    end
    
    % 绘制性能曲线
    figure('Position', [200, 200, 600, 400]);
    plot(sizes, times, 'o-', 'LineWidth', 2, 'MarkerSize', 8);
    xlabel('矩阵大小');
    ylabel('计算时间 (秒)');
    title('匈牙利算法性能测试');
    grid on;
end

3. 实际应用示例

function practical_examples()
% 实际应用场景示例

fprintf('=== 匈牙利算法实际应用示例 ===\n\n');

%% 示例1: 工作任务分配
fprintf('示例1: 工作任务分配\n');
workers = {'张三', '李四', '王五', '赵六'};
tasks = {'编程', '测试', '文档', '设计'};

% 成本矩阵:每个工人完成每个任务的时间(小时)
time_cost = [
    5, 8, 6, 7;  % 张三
    6, 5, 9, 8;  % 李四
    8, 7, 5, 6;  % 王五
    7, 6, 8, 5   % 赵六
];

[assignment, total_time] = hungarian_algorithm(time_cost);

fprintf('最优工作分配:\n');
for i = 1:length(workers)
    task_idx = assignment(i);
    fprintf('%s -> %s (耗时: %d小时)\n', ...
        workers{i}, tasks{task_idx}, time_cost(i, task_idx));
end
fprintf('总耗时: %d小时\n\n', total_time);

%% 示例2: 车辆调度问题
fprintf('示例2: 车辆调度问题\n');
vehicles = {'货车A', '货车B', '货车C'};
deliveries = {'订单1', '订单2', '订单3'};

% 成本矩阵:运输距离(公里)
distance_cost = [
    15, 25, 20;  % 货车A
    20, 15, 30;  % 货车B
    25, 30, 15   % 货车C
];

[assignment, total_distance] = hungarian_algorithm(distance_cost);

fprintf('最优车辆调度:\n');
for i = 1:length(vehicles)
    delivery_idx = assignment(i);
    fprintf('%s -> %s (距离: %d公里)\n', ...
        vehicles{i}, deliveries{delivery_idx}, distance_cost(i, delivery_idx));
end
fprintf('总距离: %d公里\n\n', total_distance);

%% 示例3: 资源分配
fprintf('示例3: 资源分配\n');
projects = {'项目A', '项目B', '项目C', '项目D'};
resources = {'团队1', '团队2', '团队3', '团队4'};

% 成本矩阵:完成项目的预计成本(万元)
cost_matrix = [
    50, 60, 55, 65;
    65, 55, 70, 60;
    60, 70, 50, 55;
    55, 65, 60, 50
];

[assignment, total_cost] = hungarian_algorithm(cost_matrix);

fprintf('最优资源分配:\n');
for i = 1:length(resources)
    project_idx = assignment(i);
    fprintf('%s -> %s (成本: %d万元)\n', ...
        resources{i}, projects{project_idx}, cost_matrix(i, project_idx));
end
fprintf('总成本: %d万元\n', total_cost);

end

4. 使用说明

% 使用方法示例脚本
% hungarian_usage_example.m

clear; clc; close all;

%% 基本使用方法
fprintf('=== 基本使用方法 ===\n');

% 创建成本矩阵
cost_matrix = [
    10, 15, 20, 25;
    15, 10, 25, 20;
    20, 25, 10, 15;
    25, 20, 15, 10
];

fprintf('成本矩阵:\n');
disp(cost_matrix);

% 运行匈牙利算法
[assignment, total_cost] = hungarian_algorithm(cost_matrix);

fprintf('分配结果:\n');
for i = 1:length(assignment)
    fprintf('工人%d -> 任务%d (成本: %d)\n', i, assignment(i), cost_matrix(i, assignment(i)));
end
fprintf('总成本: %d\n\n', total_cost);

%% 运行完整演示
fprintf('按任意键运行完整演示...\n');
pause;
main_hungarian_demo();

%% 运行实际应用示例
fprintf('\n按任意键运行实际应用示例...\n');
pause;
practical_examples();

主要功能特点

  1. 完整的匈牙利算法实现:包含所有核心步骤
  2. 详细的可视化:成本矩阵热图和分配关系图
  3. 性能测试:不同规模矩阵的计算时间分析
  4. 实际应用示例:工作任务分配、车辆调度、资源分配等场景
  5. 错误检查:验证分配的有效性

参考代码 匈牙利算法实现任务分配 www.3dddown.com/cna/63742.html

运行方法

% 直接运行主演示程序
main_hungarian_demo();

% 或运行实际应用示例
practical_examples();

% 或使用自定义成本矩阵
your_cost_matrix = [...];  % 输入您的成本矩阵
[assignment, cost] = hungarian_algorithm(your_cost_matrix);
posted @ 2025-12-12 16:06  修BUG狂人  阅读(0)  评论(0)    收藏  举报