求一个矩阵中的鞍点

题目描述

T248896 05-17-C02-求一个矩阵中的鞍点(L4)

题目描述

编程求一个4×4矩阵(就是二维数组)中的鞍点,如果没有鞍点,则输出提示信息。

鞍点是二维数组中的一个元素,它在它所在那一行上最大,在它所在那一列上最小。

输入格式

输入数据占4行,每行有4个整数,范围不超过int型的范围。

输出格式

如果不存在鞍点,则输出"no saddle";如果存在鞍点,则输出所有鞍点,每个鞍点占一行,为3个整数,分别表示鞍点的值,以及它的行号和列号(行号和列号均从1开始计起),多个鞍点先按行优先、再按列优先的顺序输出。

输入输出样例 #1

输入 #1

```

5 12 23 56 19 28 37 46 -12 -34 6 8 97 25 -7 45

```

输出 #1

```

8 3 4

```

输入输出样例 #2

输入 #2

```

5 12 23 56 19 28 37 46 -12 -34 6 58 97 25 -7 45

```

输出 #2

```

no saddle

```

输入输出样例 #3

输入 #3

```

70 -77 -93 -25 55 -64 -36 -10 63 -91 -22 -12 55 20 -59 -81

```

输出 #3

```

55 2 1

55 4 1

```

输入输出样例 #4

输入 #4

```

28 -5 50 71 4 -44 12 18 70 30 -47 36 -54 -70 -54 -54

```

输出 #4

```

-54 4 1

-54 4 3

-54 4 4

```

说明/提示

本题出处

本题源自以下教材的编程习题:王桂平, 周祖松, 穆云波, 葛昌威编著. C++趣味编程及算法入门. 北京大学出版社, 2024年出版.

一、题目分析

题目要求在一个 4×4 的矩阵中寻找 "鞍点"。鞍点的定义是:矩阵中的一个元素,它既是所在行的最大值,又是所在列的最小值。若存在多个鞍点,需按行优先、列优先的顺序输出(即先按行号从小到大,同一行内按列号从小到大);若不存在鞍点,输出 "no saddle"。

二、核心思路

要找到鞍点,需分两步判断每个元素:

  1. 该元素是否是其所在行的最大值;
  2. 该元素是否是其所在列的最小值。

为提高效率,可先预处理矩阵,计算出每一行的最大值和每一列的最小值,存储在临时变量中,再逐个元素验证是否同时满足上述两个条件。

三、代码实现步骤详解

1. 引入头文件与命名空间

cpp

运行

复制代码
#include<bits/stdc++.h>  // 包含所有标准库,简化代码
using namespace std;

2. 定义矩阵并读取输入

cpp

运行

复制代码
int a[5][5];  // 定义5×5数组(下标1~4用于存储4×4矩阵,0行0列用于存储中间结果)
int i,j;

// 读取4×4矩阵,行号i和列号j从1开始(方便后续输出行号列号)
for(i = 1; i < 5; i++){  // i=1~4(4行)
    for(j = 1; j < 5; j++){  // j=1~4(4列)
        cin >> a[i][j];  // 存储元素到a[i][j]
    }
}

说明 :使用 5×5 数组而非 4×4,是为了用a[0][j]存储第 j 列的最小值,a[i][0]存储第 i 行的最大值,避免占用有效数据的下标。

3. 计算每列的最小值(存储在第 0 行)

cpp

运行

复制代码
for(j = 1; j < 5; j++){  // 遍历每一列(j=1~4)
    int mn = a[1][j];  // 初始假设第j列第1行的元素是最小值
    for(i = 2; i < 5; i++){  // 比较第j列的其他元素(行i=2~4)
        if(a[i][j] < mn){  // 若找到更小的元素
            mn = a[i][j];  // 更新最小值
        }
    }
    a[0][j] = mn;  // 第j列的最小值存入a[0][j]
}

4. 计算每行的最大值(存储在第 0 列)

cpp

运行

复制代码
for(i = 1; i < 5; i++){  // 遍历每一行(i=1~4)
    int mx = a[i][1];  // 初始假设第i行第1列的元素是最大值
    for(j = 2; j < 5; j++){  // 比较第i行的其他元素(列j=2~4)
        if(a[i][j] > mx){  // 若找到更大的元素
            mx = a[i][j];  // 更新最大值
        }
    }
    a[i][0] = mx;  // 第i行的最大值存入a[i][0]
}

5. 查找并输出鞍点

cpp

运行

复制代码
bool flag = false;  // 标记是否找到鞍点,初始为false

// 按行优先、列优先遍历所有元素(i=1~4行,j=1~4列)
for(i = 1; i < 5; i++){
    for(j = 1; j < 5; j++){
        // 若当前元素既是所在行的最大值(等于a[i][0]),又是所在列的最小值(等于a[0][j])
        if(a[i][j] == a[i][0] && a[i][j] == a[0][j]){
            // 输出:元素值、行号、列号(行号列号从1开始,与i、j直接对应)
            cout << a[i][j] << " " << i << " " << j << endl;
            flag = true;  // 标记已找到鞍点
        }
    }
}

// 若未找到鞍点,输出提示信息
if(flag == false){
    cout << "no saddle" << endl;
}

四、关键逻辑解析

  1. 数组下标设计 :用a[1][1]~a[4][4]存储 4×4 矩阵的有效元素,a[0][j](j=1~4)存储第 j 列的最小值,a[i][0](i=1~4)存储第 i 行的最大值。这种设计避免了额外定义数组,且方便直接通过 i、j 获取行号和列号(无需转换)。

  2. 行最大值与列最小值的预处理:先一次性计算所有行的最大值和列的最小值,存储在第 0 行和第 0 列,后续判断时直接读取,避免重复计算,提高效率。

  3. 鞍点判断条件 :元素a[i][j]必须同时满足:

    • 等于所在行的最大值(a[i][j] == a[i][0]
    • 等于所在列的最小值(a[i][j] == a[0][j]
  4. 输出顺序 :遍历顺序为i从1到4(行优先),同一行内j从1到4(列优先),自然满足题目要求的输出顺序。

五、示例测试解析

样例 1 输入:

plaintext

复制代码
5 12 23 56
19 28 37 46
-12 -34 6 8
97 25 -7 45
  • 计算列最小值(a[0][j]):第 1 列:min (5,19,-12,97) = -12第 2 列:min (12,28,-34,25) = -34第 3 列:min (23,37,6,-7) = -7第 4 列:min (56,46,8,45) = 8

  • 计算行最大值(a[i][0]):第 1 行:max (5,12,23,56) = 56第 2 行:max (19,28,37,46) = 46第 3 行:max (-12,-34,6,8) = 8第 4 行:max (97,25,-7,45) = 97

  • 判断鞍点 :第 3 行第 4 列的元素8,等于行最大值(8)和列最小值(8),因此是鞍点。输出:8 3 4

样例 3 输入:

plaintext

复制代码
70 -77 -93 -25
55 -64 -36 -10
63 -91 -22 -12
55 20 -59 -81
  • 列最小值(第 1 列):min (70,55,63,55) = 55

  • 行最大值:第 2 行:max (55,-64,-36,-10) = 55第 4 行:max (55,20,-59,-81) = 55

  • 鞍点 :第 2 行第 1 列(55)和第 4 行第 1 列(55)均满足条件,按行优先输出,结果为:55 2 1``55 4 1

样例 4 输入:

plaintext

复制代码
28 -5 50 71
4 -44 12 18
70 30 -47 36
-54 -70 -54 -54
  • 行最大值(第 4 行):max(-54,-70,-54,-54) = -54

  • 列最小值:第 1 列:min (28,4,70,-54) = -54第 3 列:min (50,12,-47,-54) = -54第 4 列:min (71,18,36,-54) = -54

  • 鞍点 :第 4 行中列 1、3、4 的元素均为 - 54,且满足条件,输出:-54 4 1``-54 4 3``-54 4 4

六、完整代码

cpp

运行

复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
    int a[5][5],i,j;
    // 读取4×4矩阵(行号、列号从1开始)
    for(i = 1; i < 5; i++){
        for(j = 1; j < 5; j++)
            cin >> a[i][j];
    }
    // 计算每列的最小值,存储在第0行
    for(j = 1; j < 5; j++){
        int mn = a[1][j];
        for(i = 2; i < 5; i++){
            if(a[i][j] < mn) mn = a[i][j];
        }
        a[0][j] = mn;
    }
    // 计算每行的最大值,存储在第0列
    for(i = 1; i < 5; i++){
        int mx = a[i][1];
        for(j = 2; j < 5; j++){
            if(a[i][j] > mx) mx = a[i][j];
        }
        a[i][0] = mx;
    }
    // 查找并输出鞍点
    bool flag = false;
    for(i = 1; i < 5; i++){
        for(j = 1; j < 5; j++){
            if(a[i][j] == a[i][0] && a[i][j] == a[0][j]){
                cout << a[i][j] << " " << i << " " << j << endl;
                flag = true;
            }
        }
    }
    // 未找到鞍点时输出提示
    if(flag == false) cout << "no saddle" << endl;
    return 0;
}
相关推荐
Greedy Alg7 小时前
LeetCode 74. 搜索二维矩阵
算法
小猪咪piggy7 小时前
【算法】day7 滑动窗口+二分查找
算法
仟千意7 小时前
数据结构:二叉树
数据结构·算法
一水鉴天8 小时前
整体设计 逻辑系统程序 之34七层网络的中台架构设计及链路对应讨论(含 CFR 规则与理 / 事代理界定)
人工智能·算法·公共逻辑
DuHz8 小时前
C程序中的数组与指针共生关系
linux·c语言·开发语言·嵌入式硬件·算法
而后笑面对8 小时前
力扣2025.10.19每日一题
算法·leetcode·职场和发展
·白小白8 小时前
力扣(LeetCode) ——11.盛水最多的容器(C++)
c++·算法·leetcode
沐浴露z9 小时前
【JVM】详解 垃圾回收
java·jvm·算法
代码欢乐豆10 小时前
编译原理机测客观题(7)优化和代码生成练习题
数据结构·算法·编译原理