XTU-OJ 1268-鞍点

题目描述

给一个矩阵An×m,其元素aij我们称其为鞍点,则满足它是第i行里最大值且第j列里最小值或者第i行里最小值且第j列里最大值。 现在给你一个矩阵,请求出其所有的鞍点。

输入

第一行是一个整数T(1≤T≤100),表示样例的个数。 每个样例的第一行是两个整数n,m(1≤n,m≤100),表示矩阵的行和列的大小。

以后的n行,每行m个整数,表示元素aij(0≤aij≤1000)。

输出

如果存在鞍点,则先输出一行,鞍点个数,。 然后按行优先原则,输出所有鞍点坐标(坐标从0开始计数)和鞍点的值,每行输出一个。

如果不存在鞍点,则输出"None"。

样例输入

复制代码
2
3 3
1 2 3
4 5 4
1 4 3
3 3
1 5 2
7 3 6
4 8 9

样例输出

复制代码
3
0 2 3
1 0 4
1 2 4
None

解题思路:

方法一:

逐行逐列的考虑,在每一行时,找到该行的最大、最小值,然后判断最大值在此列中是否是最小值、 判断最小值在此列中是否是最大值。 依次类推。

注意第 52 行,有个判断 最大值和最小值是否相等的,如果相等,要直接continue掉,因为可能会重复记录。

cpp 复制代码
#include <stdio.h>

int T,n,m;
int matrix[105][105];
int record[10004][4];

bool exam1(int row,int Min){
    for (int i = 0; i < n; i ++)
        if (matrix[i][row] < Min)
            return false;             
    return true;
}
bool exam2(int row,int Max){
    for (int i = 0; i < n; i ++)
        if (matrix[i][row] > Max)
            return false;        
    return true;
}

int main()
{
    scanf("%d",&T);
    while ( T --)
    {
        bool flag;
        int cnt = 0, max = 0, min = 0;
        scanf("%d %d",&n,&m);
        for (int i = 0; i < n; i ++)            // 矩阵输入
            for (int j = 0; j < m; j ++)
                scanf("%d",&matrix[i][j]);

        for (int i = 0; i < n; i ++)
        {
            max = min = matrix[i][0];           // 找到一行中的 最大、最小值
            for (int j = 0; j < m; j ++)   
            {
                if (matrix[i][j] > max)
                    max = matrix[i][j];
                if (matrix[i][j] < min)
                    min = matrix[i][j];
            }
            for (int k = 0; k < m; k ++)
            {
                if (matrix[i][k] == max)        // 检查行最大值,是不是列最小值
                {
                    flag = exam1(k,max);
                    if ( flag)                  // 如果是的,则是鞍点,记录在record数组中
                    {
                        record[cnt][0] = i, record[cnt][1] = k;
                        record[cnt][2] = matrix[i][k];
                        cnt ++;
                        if (max == min)  continue;  // **特殊情况**
                    }
                }
                if (matrix[i][k] == min)        // 检查行最小值,是不是列最大值
                {
                    flag = exam2(k,min);        // 如果是的,则是鞍点,记录在record数组中
                    if ( flag)
                    {
                        record[cnt][0] = i, record[cnt][1] = k;
                        record[cnt][2] = matrix[i][k];
                        cnt ++;                   
                    }
                }
            }
        }

        if (cnt == 0)   {puts("None"); continue;}       // 输出
        printf("%d\n",cnt);
        for (int i = 0; i < cnt; i ++)
            printf("%d %d %d\n",record[i][0],record[i][1],record[i][2]);
    }
    return 0;
}

方法二:(有些麻烦,不推荐)

统一考察法,先把所有行列的最大值和最小值做好标记。最后计算,同一位置上的数,即使最大值又是最小值,则即为鞍点。

最小值记1,最大值记2,两个相等记3。则 1*2 = 2 为鞍点,1*3 、2*3、3*3 的点均为鞍点。

cpp 复制代码
#include <stdio.h>

int remember[10005][4];
int matrix[105][105];
int tagLine[105][105];        // 行标记
int tagRow[105][105];         // 列标记
  int T,n,m,cnt;
int main()
{
  
    scanf("%d",&T);
    while ( T --)
    {
        scanf("%d %d",&n,&m);
        for (int i = 0; i < n; i ++)
            for (int j = 0; j < m; j ++)
                scanf("%d",&matrix[i][j]);

        for (int i = 0; i < n; i ++)            //  行考察
        {
            int numMin = 1001, numMax = -1;
            for (int j = 0; j < m; j ++)
            {
                if (matrix[i][j] < numMin)  numMin = matrix[i][j];
                if (matrix[i][j] > numMax)  numMax = matrix[i][j];
            }
            for (int k = 0; k < m; k ++)
            {
                if (numMax == numMin)            tagLine[i][k] = 3;   // 最小、大相等置 3
                else if (matrix[i][k] == numMin) tagLine[i][k] = 1;   // 本行最小值置 1
                else if (matrix[i][k] == numMax) tagLine[i][k] = 2;   // 本行最大值置 2
            }
        }
        for (int i = 0; i < m; i ++)            //  列考察
        {
            int numMin = 1001, numMax = -1;
            for (int j = 0; j < n; j ++)
            {
                if (matrix[j][i] < numMin)  numMin = matrix[j][i];
                if (matrix[j][i] > numMax)  numMax = matrix[j][i];
            }
            for (int k = 0; k < n; k ++)
            {
                if (numMax == numMin)            tagRow[k][i] = 3;   // 最小、大相等置 3
                else if (matrix[k][i] == numMin) tagRow[k][i] = 1;   // 本列最小值置 1
                else if (matrix[k][i] == numMax) tagRow[k][i] = 2;   // 本列最大值置 2
            }
        }
        cnt = 0;
        for (int i = 0; i < n; i ++)
        {
            for (int j = 0; j < m; j ++)
            {
                int tag = tagLine[i][j] * tagRow[i][j];
                if (tag == 2 || tag == 3 || tag == 6 || tag == 9)
                {
                    remember[cnt][0] = i;
                    remember[cnt][1] = j;
                    remember[cnt][2] = matrix[i][j];
                    cnt ++;
                }
            }
        }
        if (cnt == 0)   {puts("None"); continue;}
        printf("%d\n",cnt);
        for (int i = 0; i < cnt; i ++)
            printf("%d %d %d\n",remember[i][0],remember[i][1],remember[i][2]);
    }
    return 0;
}
相关推荐
L_1421906873 分钟前
数据结构之排序
数据结构·算法·排序算法
zyq~11 分钟前
【课堂笔记】标签传播算法Label Propagation Algorithm(LPA)
人工智能·笔记·算法·机器学习·概率论·lpa·半监督学习
白熊18820 分钟前
【机器学习基础】机器学习入门核心算法:多分类与多标签分类算法
算法·机器学习·分类
珂朵莉MM1 小时前
2022 RoboCom 世界机器人开发者大赛(睿抗 caip) -高职组(国赛)解题报告 | 科学家
java·人工智能·python·算法·职场和发展·机器人
STY_fish_20123 小时前
手拆STL
java·c++·算法
小纭在努力3 小时前
【算法设计与分析】实验——改写二分搜索算法,众数问题(算法分析:主要算法思路),有重复元素的排列问题,整数因子分解问题(算法实现:过程,分析,小结)
数据结构·python·学习·算法·算法设计与分析·实验报告·实验
芜湖xin4 小时前
【题解-洛谷】B4278 [蓝桥杯青少年组国赛 2023] 简单算术题
算法·
理智的灰太狼4 小时前
题目 3298: 蓝桥杯2024年第十五届决赛真题-兔子集结
算法·职场和发展·蓝桥杯
kingmax542120087 小时前
【洛谷P9303题解】AC- [CCC 2023 J5] CCC Word Hunt
数据结构·c++·算法·广度优先
白熊1887 小时前
【机器学习基础】机器学习入门核心算法:XGBoost 和 LightGBM
人工智能·算法·机器学习