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;
}
相关推荐
CoovallyAIHub17 小时前
中科大DSAI Lab团队多篇论文入选ICCV 2025,推动三维视觉与泛化感知技术突破
深度学习·算法·计算机视觉
NAGNIP18 小时前
Serverless 架构下的大模型框架落地实践
算法·架构
moonlifesudo18 小时前
半开区间和开区间的两个二分模版
算法
moonlifesudo18 小时前
300:最长递增子序列
算法
CoovallyAIHub1 天前
港大&字节重磅发布DanceGRPO:突破视觉生成RLHF瓶颈,多项任务性能提升超180%!
深度学习·算法·计算机视觉
CoovallyAIHub1 天前
英伟达ViPE重磅发布!解决3D感知难题,SLAM+深度学习完美融合(附带数据集下载地址)
深度学习·算法·计算机视觉
聚客AI2 天前
🙋‍♀️Transformer训练与推理全流程:从输入处理到输出生成
人工智能·算法·llm
大怪v2 天前
前端:人工智能?我也会啊!来个花活,😎😎😎“自动驾驶”整起!
前端·javascript·算法
惯导马工2 天前
【论文导读】ORB-SLAM3:An Accurate Open-Source Library for Visual, Visual-Inertial and
深度学习·算法
骑自行车的码农2 天前
【React用到的一些算法】游标和栈
算法·react.js