52. Sort Colors && Combinations

本文深入探讨了排序颜色和组合问题的解决方法,通过详细分析两种算法的思路和实现,帮助开发者理解如何使用计数排序和递归来解决实际问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Sort Colors

 Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue.

Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.

Note: You are not suppose to use the library's sort function for this problem.

click to show follow up.

Follow up: A rather straight forward solution is a two-pass algorithm using counting sort. First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's.

Could you come up with an one-pass algorithm using only constant space?

思路: 1. 类似快排,走两遍(v=1, 分出0;v = 2,分出1)。

void partition(int A[], int n, int v) {
    int start = 0, end = n-1;
    while(start < end) {
        while(start < end && A[start] < v) ++start;
        while(start < end && A[end] >= v) --end;
        int tem = A[start];
        A[start++] = A[end];
        A[end--] = tem;
    }
}
class Solution {
public:
    void sortColors(int A[], int n) {
        partition(A, n, 1);
        partition(A, n, 2);
    }
};

 2. 计数排序。计数与重写。

class Solution {
public:
    void sortColors(int A[], int n) {
        int count[3] = {0};
        for(int i = 0; i < n; ++i) count[A[i]]++;
        int id = 0;
        for(int i = 0; i < 3; ++i) 
            for(int j = 0; j < count[i]; ++j) 
                A[id++] = i;
    }
};

 

Combinations

  Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.

For example, If n = 4 and k = 2, a solution is:

[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

思路:递归,每层从前往后逐步取元素。
void combination(int k, int num, int begin, int end, vector<int> & vec2, vector<vector<int> > &vec) {
    if(num == k) {
        vec.push_back(vec2);
        return;
    }
    for(int i = begin; i <= end; ++i) {
        vec2.push_back(i);
        combination(k, num+1, i+1, end, vec2, vec);
        vec2.pop_back();
    }
}

class Solution {
public:
    vector<vector<int> > combine(int n, int k) {
        vector<int> vec2;
        vector<vector<int> > vec;
        combination(k, 0, 1, n, vec2, vec);
        return vec;
    }
};

 

 

转载于:https://www.cnblogs.com/liyangguang1988/p/3954256.html

%% 初始化 clc; clear; close all; warning('off', 'images:imshow:all'); % 关闭所有 imshow 相关警告 % 定义路径和参数 inputFolder = 'C:\Users\pengxin916\Desktop\image'; outputFolder = 'processed_data'; targetSize = [512, 512]; % 统一分辨率 numGeneralAugment = 20; % 普通组合增强次数 numOrangeAugment = 100; % 橙绿组合增强次数 % 验证输出文件夹权限 if ~exist(outputFolder, 'dir') mkdir(outputFolder); end % 创建组合文件夹 combinations = ["blue_green", "red_green", "orange_green"]; for combo = combinations comboFolder = fullfile(outputFolder, char(combo)); if ~exist(comboFolder, 'dir') mkdir(comboFolder); end end %% 主处理流程 % 第一阶段:数据分类与预处理 fprintf('开始预处理阶段...\n'); % 获取输入文件夹中的所有图像文件 imageFiles = dir(fullfile(inputFolder, '*.jpg')); numImages = numel(imageFiles); fprintf('找到 %d 张图像\n', numImages); for i = 1:numImages try % 读取图像文件 imgPath = fullfile(inputFolder, imageFiles(i).name); img = imread(imgPath); % 验证图像是否正确读取(确保为数值类型) if ~isa(img, 'uint8') && ~isa(img, 'double') fprintf("图像 %d/%d: 无法读取或格式不正确,跳过 (%s)\n", i, numImages, imageFiles(i).name); continue; end % 统一尺寸 img = imresize(img, targetSize); % 自动分类颜色组合 combo = detectColorCombo(img); % 调试输出 if isempty(combo) || strcmp(combo, "unknown") fprintf("图像 %d/%d: 未识别的颜色组合,跳过 (%s)\n", i, numImages, imageFiles(i).name); % 显示颜色检测详情 [colorsFound, ~] = detectColorComboDebug(img); fprintf(' 检测到的颜色: %s\n', join(colorsFound, ', ')); continue; end % 确保只处理预定义的颜色组合 if ~ismember(combo, combinations) fprintf("图像 %d/%d: 不支持的颜色组合 %s,跳过\n", i, numImages, combo); continue; end % 通道分离与配准 colors = split(combo, "_"); % 确保有两种颜色 if numel(colors) ~= 2 fprintf("图像 %d/%d: 颜色组合错误 (%s),跳过\n", i, numImages, combo); continue; end % 使用圆括号索引字符串数组 color1 = colors(1); color2 = colors(2); % 提取颜色掩码 mask1 = getColorMask(img, color1); mask2 = getColorMask(img, color2); % 检查掩码有效性(提高阈值) minPixels = 500; % 提高阈值以确保足够的像素 if nnz(mask1) < minPixels || nnz(mask2) < minPixels fprintf("图像 %d/%d: 颜色掩码不完整,跳过\n", i, numImages); % 显示掩码信息 fprintf(' %s 掩码像素: %d, %s 掩码像素: %d\n', color1, nnz(mask1), color2, nnz(mask2)); continue; end % 图像配准 try % 使用改进的配准方法 [optimizer, metric] = imregconfig('multimodal'); optimizer.MaximumIterations = 100; tform = imregtform(mask2, mask1, 'similarity', optimizer, metric); aligned = imwarp(mask2, tform); catch ME fprintf("图像 %d/%d: 配准失败,使用默认变换 - %s\n", i, numImages, ME.message); tform = affine2d(eye(3)); aligned = imwarp(mask2, tform); end % 保存预处理结果 - 确保保存为RGB图像 outputPath = fullfile(outputFolder, char(combo), sprintf("pre_%03d.png", i)); % 检查输出文件夹权限 [folderPart, ~, ~] = fileparts(outputPath); if ~checkFolderWritable(folderPart) fprintf("图像 %d/%d: 无法写入文件夹 %s,跳过\n", i, numImages, folderPart); continue; end % 创建RGB图像:R通道为mask1, G通道为aligned, B通道为零 mask1_uint8 = uint8(mask1); aligned_uint8 = uint8(aligned); outputImg = cat(3, mask1_uint8, aligned_uint8, zeros(size(mask1_uint8))); % 保存图像 imwrite(outputImg, outputPath); fprintf("图像 %d/%d 预处理完成: %s\n", i, numImages, outputPath); catch ME fprintf("处理图像 %d/%d 时出错: %s\n", i, numImages, ME.message); continue; end end % 第二阶段:数据增强 fprintf('\n开始数据增强阶段...\n'); for combo = combinations comboFolder = fullfile(outputFolder, char(combo)); % 检查是否有预处理图像 preprocessedFiles = dir(fullfile(comboFolder, 'pre_*.png')); if isempty(preprocessedFiles) fprintf('警告: 组合 "%s" 没有预处理图像,跳过增强\n', combo); continue; end % 配置增强参数 if strcmp(combo, "orange_green") augmenter = imageDataAugmenter( ... "RandRotation", [-180, 180], ... "RandXScale", [0.5, 2], ... "RandYScale", [0.5, 2], ... "RandXReflection", true, ... "RandYReflection", true, ... "RandXTranslation", [-20, 20], ... "RandYTranslation", [-20, 20] ... ); numAugment = numOrangeAugment; else augmenter = imageDataAugmenter( ... "RandRotation", [-30, 30], ... "RandXScale", [0.8, 1.2], ... "RandYScale", [0.8, 1.2], ... "RandXTranslation", [-10, 10], ... "RandYTranslation", [-10, 10] ... ); numAugment = numGeneralAugment; end fprintf('开始为组合 "%s" 生成增强图像,共有 %d 个预处理图像\n', combo, numel(preprocessedFiles)); % 为每个预处理图像生成增强图像 for i = 1:numel(preprocessedFiles) imgName = preprocessedFiles(i).name; imgPath = fullfile(comboFolder, imgName); % 读取并验证图像 try testImg = imread(imgPath); % 确保图像为uint8类型 if ~isa(testImg, 'uint8') testImg = im2uint8(testImg); end % 确保图像为三通道 if ndims(testImg) == 2 testImg = cat(3, testImg, testImg, testImg); end if ndims(testImg) ~= 3 fprintf("图像 %d/%d 维度不正确 (应为3),实际为 %d\n", i, numel(preprocessedFiles), ndims(testImg)); continue; end catch ME fprintf("读取图像 %d/%d 时出错: %s\n", i, numel(preprocessedFiles), ME.message); continue; end % 创建单图像的数据存储 singleImds = imageDatastore({imgPath}, 'IncludeSubfolders', false, 'FileExtensions', '.png'); % 创建增强数据存储 augDs = augmentedImageDatastore(targetSize, singleImds, "DataAugmentation", augmenter); % 记录生成的增强图像数量 numGenerated = 0; % 重置数据存储指针 reset(augDs); % 循环生成增强图像 while numGenerated < numAugment && hasdata(augDs) try % 读取增强图像 augImg = read(augDs); % 确保图像为uint8类型且维度正确 if ~isa(augImg, 'uint8') augImg = im2uint8(augImg); end if ndims(augImg) == 2 augImg = cat(3, augImg, augImg, augImg); end % 生成输出文件名 [~, baseName, ~] = fileparts(imgName); outputPath = fullfile(outputFolder, char(combo), sprintf("%s_aug%03d.png", baseName, numGenerated+1)); % 保存增强图像 imwrite(augImg, outputPath); numGenerated = numGenerated + 1; % 显示进度 if mod(numGenerated, 10) == 0 fprintf('%d%% ', round(numGenerated/numAugment*100)); end catch ME % 详细错误提示 fprintf('E 错误详情: %s\n', ME.message); % 尝试诊断问题 try % 检查数据存储内容 peekImg = read(augDs); fprintf(' 数据存储内容类型: %s,维度: %s\n', class(peekImg), mat2str(size(peekImg))); catch innerME fprintf(' 无法读取数据存储: %s\n', innerME.message); end break; % 跳出循环,处理下一张图像 end end fprintf('完成 (%d/%d)\n', numGenerated, numAugment); % 如果生成的增强图像数量不足,给出提示 if numGenerated < numAugment fprintf(' 警告: 为图像 %d 只生成了 %d/%d 个增强图像\n', i, numGenerated, numAugment); end end end %% 自定义函数定义 function combo = detectColorCombo(img) % 转换到HSV空间 hsv = rgb2hsv(img); hue = hsv(:,:,1); sat = hsv(:,:,2); val = hsv(:,:,3); % 提取有效像素(进一步降低阈值) validPixels = hue(sat > 0.1 & val > 0.15); % 调整阈值 if isempty(validPixels) combo = "unknown"; return; end % 统计主色分布 [counts, edges] = histcounts(validPixels, 0:0.025:1); [~, idx] = sort(counts, 'descend'); idx = idx(1:min(5, numel(idx))); % 颜色范围定义(进一步优化) colorRanges = table( ... {[0, 0.05]; [0.95, 1]; [0.05, 0.15]; [0.15, 0.3]; % 红色和橙色范围 [0.3, 0.5]; [0.5, 0.65]; [0.65, 0.85]; [0.85, 0.95]}, ... % 绿色、青色、蓝色、紫色范围 ["red"; "red"; "orange"; "yellow"; "green"; "cyan"; "blue"; "purple"], ... 'VariableNames', {'Range', 'Color'} ... ); mainColors = string.empty(0, 1); for i = 1:numel(idx) binCenter = (edges(idx(i)) + edges(idx(i)+1)) / 2; for r = 1:height(colorRanges) range = colorRanges.Range{r}; if (range(1) <= binCenter && binCenter <= range(2)) || ... (range(1) > range(2) && (binCenter >= range(1) || binCenter <= range(2))) mainColors(end+1) = colorRanges.Color(r); break; end end end % 过滤颜色(保留更多颜色,只排除最不可能的) validColors = mainColors(~ismember(mainColors, ["yellow", "cyan", "purple"])); % 如果过滤后颜色不足,保留所有检测到的颜色 if numel(validColors) < 2 validColors = mainColors; end % 如果仍然不足,返回未知 if numel(validColors) < 2 combo = "unknown"; return; end uniqueColors = unique(validColors); % 如果没有找到两种不同的颜色,尝试从重复颜色中选择 if numel(uniqueColors) < 2 combo = "unknown"; return; end % 优先考虑特定颜色组合 colorPair = sort(uniqueColors(1:2)); % 检查是否包含目标颜色组合 if ismember("red", colorPair) && ismember("green", colorPair) combo = "red_green"; elseif ismember("orange", colorPair) && ismember("green", colorPair) combo = "orange_green"; elseif ismember("blue", colorPair) && ismember("green", colorPair) combo = "blue_green"; else combo = "unknown"; end end % 调试版本的颜色检测函数,返回更多信息 function [colorsFound, details] = detectColorComboDebug(img) % 此函数与detectColorCombo逻辑相同,但返回详细信息用于调试 hsv = rgb2hsv(img); hue = hsv(:,:,1); sat = hsv(:,:,2); val = hsv(:,:,3); validPixels = hue(sat > 0.1 & val > 0.15); if isempty(validPixels) colorsFound = []; details = struct(); return; end [counts, edges] = histcounts(validPixels, 0:0.025:1); [~, idx] = sort(counts, 'descend'); idx = idx(1:min(5, numel(idx))); colorRanges = table( ... {[0, 0.05]; [0.95, 1]; [0.05, 0.15]; [0.15, 0.3]; [0.3, 0.5]; [0.5, 0.65]; [0.65, 0.85]; [0.85, 0.95]}, ... ["red"; "red"; "orange"; "yellow"; "green"; "cyan"; "blue"; "purple"], ... 'VariableNames', {'Range', 'Color'} ... ); mainColors = string.empty(0, 1); for i = 1:numel(idx) binCenter = (edges(idx(i)) + edges(idx(i)+1)) / 2; for r = 1:height(colorRanges) range = colorRanges.Range{r}; if (range(1) <= binCenter && binCenter <= range(2)) || ... (range(1) > range(2) && (binCenter >= range(1) || binCenter <= range(2))) mainColors(end+1) = colorRanges.Color(r); break; end end end validColors = mainColors(~ismember(mainColors, ["yellow", "cyan", "purple"])); if numel(validColors) < 2 validColors = mainColors; end colorsFound = validColors; % 构建详细信息 details = struct(); details.numValidPixels = numel(validPixels); details.mainColors = mainColors; details.validColors = validColors; details.hueDistribution = [edges(1:end-1); counts]'; end function mask = getColorMask(img, color) % 转换到LAB空间 lab = rgb2lab(img); mask = false(size(img, 1), size(img, 2)); switch lower(color) case "red" % 优化红色检测 mask = ((lab(:,:,2) > 20 & lab(:,:,3) < 15) | (lab(:,:,2) > 30 & lab(:,:,3) > 20)); case "green" % 优化绿色检测 mask = (lab(:,:,2) < -10 & lab(:,:,3) > 5); case "blue" % 优化蓝色检测 mask = (lab(:,:,3) < -20); case "orange" % 优化橙色检测 mask = (lab(:,:,2) > 15 & lab(:,:,3) > 20); otherwise error("未知颜色类型: %s", color); end % 形态学去噪 se = strel("disk", 3); mask = imclose(imopen(mask, se), se); mask = uint8(mask) * 255; % 防止空掩码 if nnz(mask) == 0 mask = false(size(img,1), size(img,2)); end end function isWritable = checkFolderWritable(folderPath) % 检查文件夹是否可写 isWritable = false; if ~exist(folderPath, 'dir') return; end % 尝试创建临时文件 try tempFile = fullfile(folderPath, ".write_test_" + datetime('now', 'Format', 'yyyymmddHHMMSSFFF') + ".tmp"); fid = fopen(tempFile, 'w'); if fid ~= -1 fclose(fid); delete(tempFile); isWritable = true; end catch % 忽略错误 end end开始预处理阶段... 找到 26 张图像 图像 1/26: 未识别的颜色组合,跳过 (p1.jpg) 检测到的颜色: green, green, green, green, green 图像 2/26: 未识别的颜色组合,跳过 (p10.jpg) 检测到的颜色: red, red, red, red 图像 3/26: 未识别的颜色组合,跳过 (p11.jpg) 检测到的颜色: green, green, green, green 图像 4/26: 未识别的颜色组合,跳过 (p12.jpg) 检测到的颜色: red, red, red, red 图像 5/26: 未识别的颜色组合,跳过 (p13.jpg) 检测到的颜色: green, green, green, green, green 图像 6/26: 未识别的颜色组合,跳过 (p14.jpg) 检测到的颜色: red, red, red, red, orange 图像 7/26: 颜色掩码不完整,跳过 red 掩码像素: 0, green 掩码像素: 38388 图像 8/26: 未识别的颜色组合,跳过 (p16.jpg) 检测到的颜色: red, red, red, red, orange 图像 9/26: 未识别的颜色组合,跳过 (p17.jpg) 检测到的颜色: green, green, green 图像 10/26: 未识别的颜色组合,跳过 (p18.jpg) 检测到的颜色: red, red, red, red 图像 11/26: 未识别的颜色组合,跳过 (p19.jpg) 检测到的颜色: green, green 图像 12/26: 未识别的颜色组合,跳过 (p2.jpg) 检测到的颜色: cyan, cyan, cyan, cyan, blue 图像 13/26: 未识别的颜色组合,跳过 (p20.jpg) 检测到的颜色: cyan, cyan, cyan, cyan, cyan 图像 14/26: 未识别的颜色组合,跳过 (p21.jpg) 检测到的颜色: red, red, red, orange, red 图像 15/26: 未识别的颜色组合,跳过 (p22.jpg) 检测到的颜色: green, green, green, green 图像 16/26: 未识别的颜色组合,跳过 (p23.jpg) 检测到的颜色: blue, blue 图像 17/26: 未识别的颜色组合,跳过 (p24.jpg) 检测到的颜色: green, green, green, green 图像 18/26: 未识别的颜色组合,跳过 (p25.jpg) 检测到的颜色: green, green 图像 19/26: 未识别的颜色组合,跳过 (p26.jpg) 检测到的颜色: orange, orange, orange, orange, red 图像 20/26: 未识别的颜色组合,跳过 (p27.jpg) 检测到的颜色: green, green, green, green 图像 21/26: 未识别的颜色组合,跳过 (p28.jpg) 检测到的颜色: red, red, orange, red, orange 图像 22/26: 未识别的颜色组合,跳过 (p3.jpg) 检测到的颜色: green, green, green, green, green 图像 23/26: 未识别的颜色组合,跳过 (p4.jpg) 检测到的颜色: cyan, cyan, cyan, cyan, red 图像 24/26: 未识别的颜色组合,跳过 (p5.jpg) 检测到的颜色: blue, blue 图像 25/26: 未识别的颜色组合,跳过 (p6.jpg) 检测到的颜色: green, green, green 图像 26/26: 未识别的颜色组合,跳过 (p9.jpg) 检测到的颜色: green, green, green, green 开始数据增强阶段... 警告: 组合 "blue_green" 没有预处理图像,跳过增强 开始为组合 "red_green" 生成增强图像,共有 7 个预处理图像 E 错误详情: 第 1 个输入, Image, 应为以下类型之一: double, logical, uint8, uint16, single, int16 但其类型是 table。 无法读取数据存储: 没有更多可读取的数据。请使用 reset 方法重置到数据的开头。请使用 hasdata 方法检查是否有可读取的数据。 完成 (0/20) 警告: 为图像 1 只生成了 0/20 个增强图像 E 错误详情: 第 1 个输入, Image, 应为以下类型之一: double, logical, uint8, uint16, single, int16 但其类型是 table。 无法读取数据存储: 没有更多可读取的数据。请使用 reset 方法重置到数据的开头。请使用 hasdata 方法检查是否有可读取的数据。 完成 (0/20) 警告: 为图像 2 只生成了 0/20 个增强图像 E 错误详情: 第 1 个输入, Image, 应为以下类型之一: double, logical, uint8, uint16, single, int16 但其类型是 table。 无法读取数据存储: 没有更多可读取的数据。请使用 reset 方法重置到数据的开头。请使用 hasdata 方法检查是否有可读取的数据。 完成 (0/20) 警告: 为图像 3 只生成了 0/20 个增强图像 E 错误详情: 第 1 个输入, Image, 应为以下类型之一: double, logical, uint8, uint16, single, int16 但其类型是 table。 无法读取数据存储: 没有更多可读取的数据。请使用 reset 方法重置到数据的开头。请使用 hasdata 方法检查是否有可读取的数据。 完成 (0/20) 警告: 为图像 4 只生成了 0/20 个增强图像 E 错误详情: 第 1 个输入, Image, 应为以下类型之一: double, logical, uint8, uint16, single, int16 但其类型是 table。 无法读取数据存储: 没有更多可读取的数据。请使用 reset 方法重置到数据的开头。请使用 hasdata 方法检查是否有可读取的数据。 完成 (0/20) 警告: 为图像 5 只生成了 0/20 个增强图像 E 错误详情: 第 1 个输入, Image, 应为以下类型之一: double, logical, uint8, uint16, single, int16 但其类型是 table。 无法读取数据存储: 没有更多可读取的数据。请使用 reset 方法重置到数据的开头。请使用 hasdata 方法检查是否有可读取的数据。 完成 (0/20) 警告: 为图像 6 只生成了 0/20 个增强图像 E 错误详情: 第 1 个输入, Image, 应为以下类型之一: double, logical, uint8, uint16, single, int16 但其类型是 table。 无法读取数据存储: 没有更多可读取的数据。请使用 reset 方法重置到数据的开头。请使用 hasdata 方法检查是否有可读取的数据。 完成 (0/20) 警告: 为图像 7 只生成了 0/20 个增强图像 警告: 组合 "orange_green" 没有预处理图像,跳过增强 >> 请提供一份完整的修改后且适用于matlab2023版本的代码
05-15
import pandas as pd import numpy as np import matplotlib.pyplot as plt from itertools import combinations import random import time import matplotlib as mpl from tqdm import tqdm # 设置中文字体支持 plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'WenQuanYi Micro Hei'] plt.rcParams['axes.unicode_minus'] = False # ==================================================== # 任务1: 订单需求分析 # ==================================================== print("正在执行任务1: 订单需求分析...") # 加载订单数据 demand_df = pd.read_csv('OrderDemand.csv') # 计算每个区域的总需求和日均需求 region_demand = demand_df.groupby('Region')['OrderVolume'].sum().reset_index() region_demand['AvgDailyDemand'] = region_demand['OrderVolume'] / 3 region_demand_sorted = region_demand.sort_values(by='AvgDailyDemand', ascending=False) # 计算每个小时的总需求 hourly_demand = demand_df.groupby('Hour')['OrderVolume'].sum().reset_index() hourly_demand['AvgHourlyDemand'] = hourly_demand['OrderVolume'] / 3 # 识别高峰时段 peak_hours = hourly_demand.nlargest(3, 'AvgHourlyDemand')['Hour'].tolist() # 输出分析结果 print("\n=== 高需求区域Top 5 ===") print(region_demand_sorted.head(5)) print("\n=== 高峰时段 ===") print(f"高峰时段(小时): {peak_hours}") # 可视化需求分析 plt.figure(figsize=(14, 7)) bars = plt.bar(region_demand_sorted['Region'], region_demand_sorted['AvgDailyDemand'], color='skyblue') plt.title('区域日均需求分析', fontsize=16) plt.xlabel('区域', fontsize=12) plt.ylabel('日均需求', fontsize=12) plt.xticks(rotation=45) plt.grid(axis='y', linestyle='--', alpha=0.7) # 添加数据标签 for bar in bars: height = bar.get_height() plt.annotate(f'{height:.1f}', xy=(bar.get_x() + bar.get_width() / 2, height), xytext=(0, 3), textcoords="offset points", ha='center', va='bottom', fontsize=9) plt.tight_layout() plt.savefig('region_demand.png', dpi=300) plt.close() plt.figure(figsize=(14, 7)) plt.plot(hourly_demand['Hour'], hourly_demand['AvgHourlyDemand'], marker='o', linestyle='-', color='royalblue', linewidth=2.5) plt.title('小时平均需求分布', fontsize=16) plt.xlabel('小时', fontsize=12) plt.ylabel('平均需求', fontsize=12) plt.grid(True, linestyle='--', alpha=0.7) plt.xticks(range(0, 24)) # 标记高峰时段 for i, hour in enumerate(peak_hours): plt.axvline(x=hour, color='r', linestyle='--', alpha=0.8) plt.text(hour, max(hourly_demand['AvgHourlyDemand']) * (0.85 - i*0.1), f'高峰 {hour}:00', rotation=90, ha='right', va='top', color='r', fontsize=11, bbox=dict(facecolor='white', alpha=0.8, edgecolor='none')) plt.legend(['平均需求', '高峰时段'], loc='upper left') plt.tight_layout() plt.savefig('hourly_demand.png', dpi=300) plt.close() # ==================================================== # 任务2: 网络优化模型 # ==================================================== print("\n正在执行任务2: 网络优化模型...") # 加载距离矩阵 dist_matrix = pd.read_csv('DistanceMatrix.csv', index_col=0) # 分配区域到最近的DC dc_allocation = {} for region in dist_matrix.columns: closest_dc = dist_matrix[region].idxmin() dc_allocation[region] = closest_dc # 为每个DC创建服务区域列表 dc_regions = {dc: [] for dc in dist_matrix.index} for region, dc in dc_allocation.items(): dc_regions = dc_regions[dc] if region not in dc_regions: dc_regions[dc].append(region) # 生成区域坐标(模拟位置) np.random.seed(42) positions = {} for dc in dist_matrix.index: positions[dc] = (random.uniform(0, 10), random.uniform(0, 10)) for region in dc_regions[dc]: # 区域在DC附近随机分布 positions[region] = ( positions[dc][0] + random.uniform(-2, 2), positions[dc][1] + random.uniform(-2, 2) ) # 计算区域间距离 def calculate_distance(pos1, pos2): return np.sqrt((pos1[0]-pos2[0])**2 + (pos1[1]-pos2[1])**2) # 最近邻算法求解TSP def nearest_neighbor_tsp(nodes, positions): if not nodes: return [] unvisited = nodes.copy() current = unvisited.pop(0) tour = [current] while unvisited: # 找到最近邻居 nearest = min(unvisited, key=lambda x: calculate_distance(positions[current], positions[x])) tour.append(nearest) unvisited.remove(nearest) current = nearest return tour # 为每个DC规划路径 dc_paths = {} for dc, regions in dc_regions.items(): if regions: # 包含DC的节点列表 nodes = [dc] + regions path = nearest_neighbor_tsp(nodes, positions) dc_paths[dc] = path else: dc_paths[dc] = [dc] # 计算路径总距离 def calculate_path_distance(path, positions): if len(path) < 2: return 0 distance = 0 for i in range(len(path)-1): distance += calculate_distance(positions[path[i]], positions[path[i+1]]) # 添加返回起点的距离 distance += calculate_distance(positions[path[-1]], positions[path[0]]) return distance # 输出任务2结果 print("\n=== DC分配结果 ===") for dc, regions in dc_regions.items(): print(f"{dc} 服务区域: {regions}") print("\n=== 配送路径 ===") total_distance = 0 for dc, path in dc_paths.items(): path_distance = calculate_path_distance(path, positions) total_distance += path_distance path_str = ' → '.join(path) + f" → {path[0]}" if len(path) > 1 else path[0] print(f"{dc} 路径: {path_str} | 距离: {path_distance:.2f} km") print(f"总配送距离: {total_distance:.2f} km") # ==================================================== # 任务3: 多车辆路径调度模型 (修复版) # ==================================================== print("\n正在执行任务3: 多车辆路径调度模型...") # 加载车辆信息 vehicle_df = pd.read_csv('VehicleInfo.csv') vehicles = vehicle_df.to_dict('records') # 区域需求数据(来自任务1) region_demands = region_demand.set_index('Region')['AvgDailyDemand'].to_dict() # 增强版节约算法 def enhanced_savings_algorithm(depot, nodes, demands, positions, vehicles, service_time_per_demand=5): # 如果没有节点,返回空列表 if not nodes: return [] # 创建可用车辆列表的深拷贝 available_vehicles = deepcopy(vehicles) routes = [] assigned_nodes = set() # 步骤1: 创建初始路线(每个节点一条路线) for node in nodes: # 计算单点路线的需求和时间 total_demand = demands[node] travel_time = (calculate_distance(positions[depot], positions[node]) * 2) * 1.5 # 往返时间 service_time = total_demand * service_time_per_demand total_time = travel_time + service_time # 寻找合适的车辆 vehicle_found = False for i, vehicle in enumerate(available_vehicles): if vehicle['Capacity'] >= total_demand and vehicle['MaxServiceTime'] >= total_time: routes.append({ 'nodes': [node], 'demand': total_demand, 'time': total_time, 'vehicle_id': vehicle['VehicleID'] }) assigned_nodes.add(node) # 移除已使用的车辆 del available_vehicles[i] vehicle_found = True break # 如果没有找到合适的车辆,使用最小容量的车辆(即使超载) if not vehicle_found and available_vehicles: min_capacity_vehicle = min(available_vehicles, key=lambda x: x['Capacity']) routes.append({ 'nodes': [node], 'demand': total_demand, 'time': total_time, 'vehicle_id': min_capacity_vehicle['VehicleID'] }) assigned_nodes.add(node) available_vehicles.remove(min_capacity_vehicle) # 步骤2: 计算节约值矩阵 savings = [] for i, j in combinations(nodes, 2): # 如果两个点都已被分配,计算节约值 if i in assigned_nodes and j in assigned_nodes: saving = calculate_distance(positions[depot], positions[i]) + \ calculate_distance(positions[depot], positions[j]) - \ calculate_distance(positions[i], positions[j]) savings.append((i, j, saving)) # 按节约值降序排序 savings.sort(key=lambda x: x[2], reverse=True) # 步骤3: 合并路线 for i, j, saving in savings: # 找到包含i和j的路线 route_i = next((r for r in routes if i in r['nodes']), None) route_j = next((r for r in routes if j in r['nodes']), None) # 确保是两条不同的路线 if route_i is None or route_j is None or route_i == route_j: continue # 尝试不同的合并方式 merge_success = False # 方式1: i_end -> j_start if route_i['nodes'][-1] == i and route_j['nodes'][0] == j: new_nodes = route_i['nodes'] + route_j['nodes'] merge_success = True # 方式2: j_end -> i_start elif route_j['nodes'][-1] == j and route_i['nodes'][0] == i: new_nodes = route_j['nodes'] + route_i['nodes'] merge_success = True # 方式3: i_end -> j_end (需要反转j路线) elif route_i['nodes'][-1] == i and route_j['nodes'][-1] == j: new_nodes = route_i['nodes'] + list(reversed(route_j['nodes'])) merge_success = True # 方式4: i_start -> j_start (需要反转i路线) elif route_i['nodes'][0] == i and route_j['nodes'][0] == j: new_nodes = list(reversed(route_j['nodes'])) + route_i['nodes'] merge_success = True if merge_success: # 计算新路线的总需求 total_demand = sum(demands[node] for node in new_nodes) # 计算新路线的总时间 path_distance = calculate_path_distance([depot] + new_nodes + [depot], positions) travel_time = path_distance * 1.5 # 速度40km/h,转换为分钟 service_time = total_demand * service_time_per_demand total_time = travel_time + service_time # 检查车辆是否满足新路线的需求 current_vehicle_id = route_i['vehicle_id'] current_vehicle = next((v for v in vehicles if v['VehicleID'] == current_vehicle_id), None) if current_vehicle and current_vehicle['Capacity'] >= total_demand and current_vehicle['MaxServiceTime'] >= total_time: # 合并路线 new_route = { 'nodes': new_nodes, 'demand': total_demand, 'time': total_time, 'vehicle_id': current_vehicle_id } # 移除旧路线,添加新路线 routes.remove(route_i) routes.remove(route_j) routes.append(new_route) # 释放route_j的车辆 released_vehicle_id = route_j['vehicle_id'] if released_vehicle_id != current_vehicle_id: released_vehicle = next((v for v in vehicles if v['VehicleID'] == released_vehicle_id), None) if released_vehicle: available_vehicles.append(released_vehicle) # 返回格式化结果 result = [] for route in routes: result.append(( route['vehicle_id'], route['nodes'], route['demand'], route['time'] )) return result # 为每个DC规划多车辆路径 dc_vehicle_routes = {} start_time = time.time() for dc, regions in tqdm(dc_regions.items(), desc="规划车辆路径"): if regions: routes = enhanced_savings_algorithm(dc, regions, region_demands, positions, vehicles) dc_vehicle_routes[dc] = routes else: dc_vehicle_routes[dc] = [] # 输出任务3结果 print("\n=== 多车辆路径调度结果 ===") total_vehicles_used = 0 total_vehicles_available = len(vehicles) for dc, routes in dc_vehicle_routes.items(): if not routes: print(f"\n{dc} 车辆调度方案: 无可用路径") continue print(f"\n{dc} 车辆调度方案:") for vehicle_id, route_nodes, demand, time_used in routes: total_vehicles_used += 1 # 获取车辆信息 vehicle = next((v for v in vehicles if v['VehicleID'] == vehicle_id), None) if not vehicle: vehicle_capacity = "未知" vehicle_maxtime = "未知" else: vehicle_capacity = vehicle['Capacity'] vehicle_maxtime = vehicle['MaxServiceTime'] # 计算利用率 capacity_util = (demand / vehicle_capacity * 100) if vehicle_capacity > 0 else 0 time_util = (time_used / vehicle_maxtime * 100) if vehicle_maxtime > 0 else 0 # 打印结果 route_str = f"{dc} → {' → '.join(route_nodes)} → {dc}" print(f" 车辆 {vehicle_id}:") print(f" 路径: {route_str}") print(f" 需求: {demand:.2f} / {vehicle_capacity} ({capacity_util:.1f}%)") print(f" 时间: {time_used:.2f} min / {vehicle_maxtime} min ({time_util:.1f}%)") # 计算总体利用率 utilization_rate = (total_vehicles_used / total_vehicles_available * 100) if total_vehicles_available > 0 else 0 print(f"\n总使用车辆数: {total_vehicles_used} / {total_vehicles_available}") print(f"车辆利用率: {utilization_rate:.1f}%") print(f"路径规划耗时: {time.time()-start_time:.2f}秒") # ==================================================== # 保存结果 # ==================================================== # 保存任务1结果 region_demand_sorted.to_csv('region_demand_analysis.csv', index=False) hourly_demand.to_csv('hourly_demand_analysis.csv', index=False) # 保存任务2结果 dc_allocation_df = pd.DataFrame({ 'Region': list(dc_allocation.keys()), 'AssignedDC': list(dc_allocation.values()) }) dc_allocation_df.to_csv('dc_allocation.csv', index=False) # 保存任务3结果 vehicle_routes_data = [] for dc, routes in dc_vehicle_routes.items(): for vehicle_id, route_nodes, demand, time_used in routes: vehicle = next((v for v in vehicles if v['VehicleID'] == vehicle_id), None) vehicle_capacity = vehicle['Capacity'] if vehicle else 0 vehicle_routes_data.append({ 'DC': dc, 'VehicleID': vehicle_id, 'Route': ' → '.join([dc] + route_nodes + [dc]), 'TotalDemand': demand, 'VehicleCapacity': vehicle_capacity, 'CapacityUtilization(%)': (demand / vehicle_capacity * 100) if vehicle_capacity > 0 else 0, 'TotalTime(min)': time_used, 'MaxServiceTime(min)': vehicle['MaxServiceTime'] if vehicle else 0, 'TimeUtilization(%)': (time_used / vehicle['MaxServiceTime'] * 100) if vehicle else 0 }) vehicle_routes_df = pd.DataFrame(vehicle_routes_data) vehicle_routes_df.to_csv('vehicle_routes.csv', index=False) # 生成配送网络图 plt.figure(figsize=(16, 12)) # 创建颜色映射 dc_colors = {} color_palette = plt.cm.tab10.colors for idx, dc in enumerate(dist_matrix.index): dc_colors[dc] = color_palette[idx % len(color_palette)] # 绘制DC位置 for dc in dist_matrix.index: pos = positions[dc] plt.scatter(pos[0], pos[1], s=400, c=[dc_colors[dc]], marker='s', edgecolor='k', linewidth=2, zorder=10) plt.text(pos[0], pos[1], dc, fontsize=14, ha='center', va='center', fontweight='bold', zorder=11) # 绘制区域位置和路径 for dc, routes in dc_vehicle_routes.items(): color = dc_colors[dc] # 绘制该DC下的所有区域 for region in dc_regions[dc]: pos = positions[region] plt.scatter(pos[0], pos[1], s=120, c=[color], marker='o', alpha=0.8, zorder=9) plt.text(pos[0], pos[1], region, fontsize=10, ha='center', va='bottom', zorder=9) # 绘制该DC的所有车辆路径 for route in routes: _, route_nodes, _, _ = route path = [dc] + route_nodes + [dc] # 绘制路径线 for i in range(len(path)-1): start = positions[path[i]] end = positions[path[i+1]] plt.plot([start[0], end[0]], [start[1], end[1]], c=color, linestyle='-', linewidth=1.5, alpha=0.7, zorder=5) # 标记路径起点 plt.scatter(positions[dc][0], positions[dc][1], s=150, c='red', marker='*', zorder=12) # 添加图例和标题 plt.title('物流配送网络与车辆路径规划', fontsize=18) plt.xlabel('X 坐标', fontsize=14) plt.ylabel('Y 坐标', fontsize=14) plt.grid(True, linestyle='--', alpha=0.5) # 创建自定义图例 from matplotlib.lines import Line2D legend_elements = [ Line2D([0], [0], marker='s', color='w', label='配送中心(DC)', markerfacecolor='red', markersize=12), Line2D([0], [0], marker='o', color='w', label='配送区域', markerfacecolor='blue', markersize=10), Line2D([0], [0], marker='*', color='w', label='路径起点', markerfacecolor='red', markersize=12), Line2D([0], [0], color='green', lw=2, label='配送路径') ] plt.legend(handles=legend_elements, loc='upper left', fontsize=12) plt.tight_layout() plt.savefig('delivery_network.png', dpi=300) plt.close() print("\n所有结果已保存到CSV文件和图表") TypeError: list indices must be integers or slices, not str给我解决完这个问题后修正后的完整的代码
06-03
资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在当今的软件开发领域,自动化构建与发布是提升开发效率和项目质量的关键环节。Jenkins Pipeline作为一种强大的自动化工具,能够有效助力Java项目的快速构建、测试及部署。本文将详细介绍如何利用Jenkins Pipeline实现Java项目的自动化构建与发布。 Jenkins Pipeline简介 Jenkins Pipeline是运行在Jenkins上的一套工作流框架,它将原本分散在单个或多个节点上独立运行的任务串联起来,实现复杂流程的编排与可视化。它是Jenkins 2.X的核心特性之一,推动了Jenkins从持续集成(CI)向持续交付(CD)及DevOps的转变。 创建Pipeline项目 要使用Jenkins Pipeline自动化构建发布Java项目,首先需要创建Pipeline项目。具体步骤如下: 登录Jenkins,点击“新建项”,选择“Pipeline”。 输入项目名称和描述,点击“确定”。 在Pipeline脚本中定义项目字典、发版脚本和预发布脚本。 编写Pipeline脚本 Pipeline脚本是Jenkins Pipeline的核心,用于定义自动化构建和发布的流程。以下是一个简单的Pipeline脚本示例: 在上述脚本中,定义了四个阶段:Checkout、Build、Push package和Deploy/Rollback。每个阶段都可以根据实际需求进行配置和调整。 通过Jenkins Pipeline自动化构建发布Java项目,可以显著提升开发效率和项目质量。借助Pipeline,我们能够轻松实现自动化构建、测试和部署,从而提高项目的整体质量和可靠性。
修改代码,使代码符合下面模型model = @(params,X) params(1)*X(:,1).^(params(6)) + params(2)*X(:,2).^(params(7)) + ... params(3)*X(:,3).^(params(8)) + params(4)*X(:,4).^(params(9))+ ... params(5)*X(:,5).^(params(10)) ;其中参数6,7,8,9,10是从-8到8的整数%% 全局参数初始化clear; close all;c = 3e8; % 光速(m/s)lambda = 1550e-9; % 输入光波长(m)P_opt = 10e-3; % 输入光功率(W)L = 0.03; % 电极长度(m)fm_range = linspace(0.1e6,100e9,10000); % 1MHz-100GHzbase_params = struct(... 'Vpi', 3,... % 半波电压 'P_rf_dBm', 0,... % 射频功率(0dBm) 'R', 47,... % 电极阻抗 'alpha_m_dB', 10,... % 微波损耗(dB/m) 'delta', 2.7e-10,...% 速度失配参数(s/m) 'L', L,... 'P_opt', P_opt);%% 执行参数扫描与绘图 % 参数扫描范围定义param_config = { {'Vpi', linspace(0.3,10,100), 'V_{\pi} (V)', 'linear'},... {'P_rf_dBm', linspace(-60,20,100), 'P_{rf} (dBm)', 'linear'},... {'R', linspace(1,100,100), 'R (\Omega)', 'linear'},... {'alpha_m_dB', linspace(0,50,100), '\alpha_m (dB/m)', 'linear'},... {'delta', linspace(2e-10,20e-10,100), '\delta (s/m)', 'linear'},... {'m', linspace(0.01,10,100), '调制深度m', 'linear'} % 新增调制深度m参数};%% 任务1-5:绘制f3dB参数曲线figure('Position',[200,50,1000,700],'Name','f3dB vs Parameters');for i = 1:5 [X, ~, f3dB] = parameter_sweep(base_params, param_config{i}{1}, param_config{i}{2}, fm_range); subplot(2,3,i); if strcmp(param_config{i}{4}, 'log') semilogx(X, f3dB/1e9, 'LineWidth',2); else plot(X, f3dB/1e9, 'LineWidth',2); end xlabel(param_config{i}{3}), ylabel('f_{3dB} (GHz)'); title([param_config{i}{3} ' 对f_{3dB}的影响']); grid on;end%% 任务6-10:绘制K值曲线figure('Position',[300,50,1000,700],'Name',&#x27
03-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值