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;
}
相关推荐
地平线开发者4 小时前
J6B vio scenario sample
算法
BothSavage16 小时前
Trae远程开发中DeepSeek自定义模型4054错误的排查与修复
算法
小林ixn16 小时前
从暴力到KMP:一道题彻底搞懂字符串匹配的前世今生
算法
烬羽18 小时前
字符串算法入门:从反转字符串到回文判断,面试不再慌
算法·面试
先吃饱再说1 天前
判断回文字符串,从一行代码到双指针优化
算法
黄敬峰2 天前
深入理解算法核心:从递归思想、数组扁平化到快速排序
算法
得物技术2 天前
从狂野代码到按目标生产:得物推荐 AI Harness 的工程化实践|AICon 演讲整理
人工智能·算法·架构
AI小老六2 天前
SkillOpt 架构拆解:把 Skill 文本当参数,用执行轨迹训练 Agent
后端·算法·ai编程