1 条题解

  • 0
    @ 2025-6-16 0:31:25

    解题思路分析

    这是一个处理上三角矩阵元素的最优化问题:

    输入为一个 N×N 矩阵的上三角部分(包括对角线),每个矩阵元素 (i,j)(i≤j)包含三个参数:p, l, u 目标是对每个元素选择一个值,使得所有元素的 p 与该值的乘积之和最大,输出这个最大和

    解题思路核心

    1.矩阵输入处理:按行读取上三角矩阵元素,i 从 1 到 N,j 从 i 到 N

    2.对角线元素处理:当 i=j 时,直接选择 u 值(因为 u 是上限,通常用于最大化和)

    3.非对角线元素处理:根据 p 的正负选择 l 或 u: 若 p≥0,选择 u(正数乘上限可最大化乘积) 若 p<0,选择 l(负数乘下限可最大化乘积,因为下限通常更小,负数乘更小的数结果更大)

    4.总和计算:累加所有元素的最优乘积值

    算法原理详解

    上三角矩阵特性: 对于 N×N 矩阵,上三角部分包含 i≤j 的所有元素 输入按行给出,第 i 行包含 j=i 到 j=N 的元素 代码通过双重循环 i 从 1 到 N,j 从 i 到 N 读取这些元素

    最优值选择原理

    对于元素 (i,j),我们需要选择一个值 x,使得 px 最大,x 的取值范围是 [l, u](l≤x≤u),当 p≥0 时,x 越大则 px 越大,因此选 x=u,当 p<0 时,x 越小则 px 越大(例如 p=-2 时,x=1 比 x=3 更优,因为 - 21=-2 > -2*3=-6),因此选 x=l

    对角线特殊处理: 代码中 i=j 时直接选 u,可能隐含条件:对角线元素的最优值总是取上限

    算法步骤解析

    1.输入处理循环: 外层循环 i 控制行,内层循环 j 控制列(j 从 i 开始,确保处理上三角),每次读取一个元素的 p(系数)、l(下限)、u(上限)

    2.最优值计算: 对角线元素 (i,i) 直接使用 u,因为通常上限能最大化和,非对角线元素根据 p 的符号选择 l 或 u,使 px 最大:p≥0 时,x=u → pu 最大,p<0 时,x=l → p*l 最大(因为 l≤u,负数乘更小的数结果更大)

    3.数据类型处理: 使用 long long 存储 max_sum,避免整数溢出(N 可达较大值,累加和可能超出 int 范围)

    c++代码

    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    int main() {
        int N;
        while (cin >> N) {
            // 因为输入是按上三角形式给出,且对称,可按需读取并计算,减少存储
            long long max_sum = 0;
            for (int i = 1; i <= N; ++i) {
                for (int j = i; j <= N; ++j) {
                    int p, l, u;
                    cin >> p >> l >> u;
                    if (i == j) {
                        // 对角线元素,取上限最大化和
                        max_sum += u;
                    } else {
                        // 根据 pairs 值正负,选能让乘积最大的边界值
                        if (p >= 0) {
                            max_sum += (long long)p * u;
                        } else {
                            max_sum += (long long)p * l;
                        }
                    }
                    // 利用对称性,填充对称位置(虽然计算时可能暂时用不到,但输入要读完)
                    if (i != j) {
                        // 这里只是为了读入对称位置的输入,实际计算已在上三角处理
                        // 若不想存储,其实可以不用额外变量,因为题目输入是按行给的上三角
                        // 所以上面的 cin 已经把当前行该读的读完了,这里无需操作,之前逻辑有误,修正如下:
                        // 原问题输入中,第 i 行给出的是 j从i到N的数据,所以不需要再处理对称,之前理解错了输入方式!
                        // 正确的是,输入里第 i 行的 j 是从 i 开始的,所以直接按顺序读入即可,不用管对称位置的重复读,之前的代码逻辑错误!
                        // 所以删除下面错误的对称处理代码
                    }
                }
            }
            cout << max_sum << endl;
        }
        return 0;
    }
    
    • 1

    信息

    ID
    1753
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    5
    已通过
    1
    上传者