BM61 矩阵最长递增路径

文章描述了一个关于矩阵问题的算法挑战,要求找到一条最长的递增路径。通过使用引用作为函数参数可以避免复制大对象的开销,提高效率。解决方案中采用了深度优先搜索(DFS)策略,并使用vis矩阵记录已访问单元格,确保路径的唯一性。最终返回最长递增路径的长度。

注意这里函数传参必须用引用,不然会TLE,找了好久的bug.....

引用的目的主要用于在函数参数传递中,解决大块数据或对象的传递效率和空间不如意的问题。用引用传递函数的参数,能保证参数传递中不产生副本,提高传递的效率,且通过const的使用,保证了引用传递的安全性。

描述

给定一个 n 行 m 列矩阵 matrix ,矩阵内所有数均为非负整数。 你需要在矩阵中找到一条最长路径,使这条路径上的元素是递增的。并输出这条最长路径的长度。

这个路径必须满足以下条件:

1. 对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到边界外。

2. 你不能走重复的单元格。即每个格子最多只能走一次。

#include <climits>
#include <cstdio>
#include <utility>
#include <vector>
class Solution {
  public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 递增路径的最大长度
     * @param matrix int整型vector<vector<>> 描述矩阵的每个数
     * @return int整型
     */
    int Max = 0;
    int m, n;
    int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    vector<pair<int, int>> road;
    void dfs(vector<vector<int> >& matrix, vector<vector<bool>> &vis,
             pair<int, int> path, int cnt) {
        int x = path.first, y = path.second;

        if (vis[x][y]) return;
road.push_back(path);
        vis[x][y] = true;
        for (int i = 0; i < 4; i++) {
            int nxtx = x + dirs[i][0];
            int nxty = y + dirs[i][1];

            if (nxtx >= 0 && nxtx < m && nxty >= 0 && nxty < n &&
                    matrix[nxtx][nxty] > matrix[x][y]) {
                dfs(matrix, vis, make_pair(nxtx, nxty), cnt + 1);
            } else  if (cnt > Max) {
                Max = cnt;
                // for (auto i : road) {
                //     cout << i.first << " " << i.second << endl;
                // }
            }
        }
        road.pop_back();
        vis[x][y] = false;
        return ;

    }
    int solve(vector<vector<int> >& matrix) {
        // write code here
        m = matrix.size(), n = matrix[0].size();
        vector<vector<bool>> vis(m, vector<bool>(n, false));
        vector<pair<int, int>> path;
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++) {
                dfs(matrix, vis, make_pair(i, j), 1);
            }
        return Max;
    }
};

当 `Bm` 矩阵为 4x3 矩阵时,需要对原代码中的部分内容进行修改以适配新的矩阵维度。以下是修改后的 `SpeedCurrent_MPC_Simulink` 函数代码: ```matlab function uq = SpeedCurrent_MPC_Simulink(omega, iq, p, r) % 带速度和电流约束的非级联MPC(PMSM专用),兼容Simulink代码生成 % 输入: omega(当前速度, rad/s), iq(当前q轴电流, A), p(当前位置, rad), r(位置参考, rad) % 输出: uq(q轴电压指令, V), ud_comp(d轴电压补偿, V,此处设为0,可扩展) %% 0. 显式初始化所有变量(优先级最高,解决未定义错误) % 输出变量初始化 uq = 0.0; % q轴电压指令(标量,double) ud_comp = 0.0; % d轴补偿(固定为0,标量,double) % 输入变量类型转换(按实际输入格式调整,此处转为single) omega = single(omega); iq = single(iq); p = single(p); r = single(r); % 中间变量预初始化(核心修复:确保所有变量有初始值) Nc = 16; % 控制时域需提前定义(用于Delta_U尺寸) Delta_U = zeros(Nc, 1, 'double'); % 二次规划输出(Nc×1,double) Delta_uq = 0.0; % q轴电压增量(标量,double) uq_current = 0.0; % 当前q轴电压指令(标量,double) uq_prev = 0.0; % 前一时刻电压(适配persistent初始化) %% 1. 关键参数定义(预定义所有常量,避免未定义错误) % 采样与硬件参数 Tms = 0.001; % 采样时间 (s) u_max = 310.0; % 最大相电压(380V电网→直流母线√2×220≈310V) id = 0.0; % d轴电流指令(表贴式电机弱磁前设为0,double) % 电机参数(根据实际PMSM调整,此处为示例值) J = 0.020; % 转动惯量 (kg·m²) B = 0.008; % 粘性阻尼系数 (N·m/(rad/s)) P = 4; % 极对数 Kt = 1.0; % 转矩系数 (N·m/A) R = 0.4; % 定子电阻 (Ω) Lq = 6e-3; % q轴电感 (H) Ld = 6e-3; % d轴电感 (H)(表贴式电机Ld=Lq) Psi_f = 0.186; % 永磁磁链 (Wb) % MPC核心参数 Np = 24; % 预测时域(步数,需≥Nc) % Nc已在开头初始化(控制时域,步数) % 物理约束(硬件/安全限制) omega_max = 3000.0; % 最大速度 (rad/s) iq_max = 40.0; % 最大q轴电流 (A) delta_uq_max = 20; % q轴电压增量约束 (V) %% 2. PMSM状态空间模型(dq轴4阶模型:id, iq, omega, p) % 状态方程:dx/dt = Am*x + Bm*u(u=[ud; uq; 新增控制量]) Am = [ -R/Ld, omega, -Psi_f/Ld, 0; -omega , -R/Lq, 0, 0; 0, (3*P*Kt)/(2*J), -B/J, 0; 0, 0, 1, 0]; % 4×4状态矩阵(double) % 输入矩阵(ud控制id,uq控制iq/omega,新增控制量) Bm = [1/Ld, 0, 0; 0, 1/Lq, 0; 0, 0, 0; 0, 0, 0]; % 4×3输入矩阵(double) % 输出矩阵(关注iq、omega、p三个被控量) Cm = [0, 1, 0, 0; % 输出1:iq 0, 0, 1, 0; % 输出2:omega 0, 0, 0, 1]; % 输出3:p ny = size(Cm, 1); % 输出维度(ny=3,double) %% 3. 模型离散化(零阶保持ZOH,适配数字控制) % 增广矩阵用于ZOH离散化:[Am Bm; 0 0](7×7) aug_mat = [Am, Bm; zeros(3, size(Am,2)+size(Bm,2))]; % 7×7增广矩阵(double) M = expm(aug_mat * Tms); % 矩阵指数实现ZOH(double) Ad = M(1:4, 1:4); % 4×4离散状态矩阵(double) Bd = M(1:4, 5:7); % 4×3离散输入矩阵(double) %% 4. MPC增广模型(状态+前一输入,实现增量控制) % 增广状态:[id; iq; omega; p; uq_prev](5×1) nx_aug = 5; % 增广状态维度 nu_aug = 1; % 控制输入维度(仅Δuq) % 增广状态矩阵(5×5,double) A_aug = [Ad, Bd(:,2); % 原状态对uq的响应 zeros(1, 4), 1 ];% 前一电压传递:uq_prev(k+1)=uq(k) % 增广输入矩阵(5×1,double,输入为Δuq) B_aug = [Bd(:,2); 1]; % 原状态对Δuq的响应 + uq(k)=uq_prev+Δuq % 增广输出矩阵(3×5,double) C_aug = [Cm, zeros(ny, 1)]; % 输出与前一输入无关 %% 5. 预测矩阵构建(Np步预测,double类型) phi = zeros(Np*ny, nx_aug, 'double'); F = zeros(Np*ny, Nc*nu_aug, 'double'); for i = 1:Np % 填充phi:第i步状态预测(A_aug^i * x_aug) A_aug_pow = A_aug^i; phi((i-1)*ny+1:i*ny, :) = C_aug * A_aug_pow; % 填充F:第i步控制影响(仅控制时域内的Δuq) for j = 1:min(i, Nc) A_aug_pow_ij = A_aug^(i-j); F((i-1)*ny+1:i*ny, j) = C_aug * A_aug_pow_ij * B_aug; end end %% 6. 权重矩阵与参考轨迹(均为double类型) % 输出权重矩阵Q_bar(对角矩阵,突出位置控制权重) Q_iq = 8000; % iq权重 Q_omega = 8000; % 速度权重 Q_theta = 8000; % 位置权重 R_u = 0.01; % 增量权重(标量,double) Q_bar = zeros(Np*ny, Np*ny, 'double'); for i = 1:Np % 第i步的iq权重(Q_iq)和omega权重(Q_omega) Q_bar((i-1)*ny+1, (i-1)*ny+1) = Q_iq; % iq权重 Q_bar((i-1)*ny+2, (i-1)*ny+2) = Q_omega; % omega权重 Q_bar((i-1)*ny+3, (i-1)*ny+3) = Q_theta; % p权重 end % 控制权重矩阵R_bar(抑制电压增量波动) R_bar = kron(eye(Nc, 'double'), R_u); % Nc×Nc对角矩阵(double) % 参考轨迹生成(位置→速度→电流,强制double) omega_ref = abs(r - p) ; % 由位置误差计算速度参考 omega_ref = max(min(omega_ref, omega_max), -omega_max); % 速度限幅 iq_ref = (J*(omega_ref - omega) + B*omega) / (3*P*Kt/2); % 转矩平衡求电流参考 iq_ref = max(min(iq_ref, iq_max), -iq_max); % 电流限幅 % 参考向量强制转为double(核心修复:避免r_seq为single) ref_single = [iq_ref; omega_ref; r]; ref_double = double(ref_single); r_seq = repmat(ref_double, Np, 1); % 扩展为Np步参考(double) %% 7. 增广状态向量(当前状态+前一电压,double类型) persistent uq_prev_persist; % 用persistent保存前一时刻电压 if isempty(uq_prev_persist) uq_prev_persist = 0.0; % 首次调用初始化(double) end uq_prev = uq_prev_persist; % 关联persistent变量 % 增广状态:[id; iq; omega; p; uq_prev](强制double) x_aug_current = double([id; iq; omega; p; uq_prev]); %% 8. 二次规划问题构建(适配Simulink代码生成) % 目标函数:min(0.5*ΔU'*H*ΔU + ΔU'*E) H = F' * Q_bar * F + R_bar; % 二次项矩阵(Nc×Nc,double) pred_error = phi * x_aug_current - r_seq; % 预测误差(double) E = double(F' * Q_bar * pred_error); % 线性项(Nc×1,double,核心修复) % 约束条件(电压增量限幅,double) lb = -delta_uq_max * ones(Nc, 1); % 最小增量(Nc×1) ub = delta_uq_max * ones(Nc, 1); % 最大增量(Nc×1) % 优化选项(关闭显示,固定算法,适配代码生成) options = optimoptions('quadprog','Algorithm','active-set'); % 求解二次规划(所有输入均为double,双重初始化Delta_U) x0 = zeros(Nc, 1, 'double'); % 初始搜索点 Delta_U = zeros(Nc, 1, 'double'); % 再次初始化,避免歧义 Delta_U = quadprog(H, E, [], [], [], [], lb, ub, x0, options); %% 9. 控制量计算与限幅 Delta_uq = Delta_U(1); % 取第一个控制增量(仅用控制时域第一步) uq_current = uq_prev + Delta_uq; % 计算当前电压 % 电压幅值限幅(确保不超过直流母线电压) uq_current = max(min(uq_current, u_max), -u_max); % 更新前一时刻电压(供下一周期使用) uq_prev_persist = uq_current; %% 10. 输出赋值 uq = uq_current; end ``` ### 主要修改点: 1. **`Bm` 矩阵维度修改**:将 `Bm` 矩阵修改为 4x3 矩阵,以适配新增的控制量。 2. **增广矩阵维度修改**:由于 `Bm` 矩阵维度变化,增广矩阵 `aug_mat` 的维度从 6x6 变为 7x7。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值