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;
}
相关推荐
莫叫石榴姐28 分钟前
数据科学与SQL:组距分组分析 | 区间分布问题
大数据·人工智能·sql·深度学习·算法·机器学习·数据挖掘
茶猫_1 小时前
力扣面试题 - 25 二进制数转字符串
c语言·算法·leetcode·职场和发展
Hera_Yc.H2 小时前
数据结构之一:复杂度
数据结构
肥猪猪爸3 小时前
使用卡尔曼滤波器估计pybullet中的机器人位置
数据结构·人工智能·python·算法·机器人·卡尔曼滤波·pybullet
linux_carlos3 小时前
环形缓冲区
数据结构
readmancynn4 小时前
二分基本实现
数据结构·算法
萝卜兽编程4 小时前
优先级队列
c++·算法
Bucai_不才4 小时前
【数据结构】树——链式存储二叉树的基础
数据结构·二叉树
盼海4 小时前
排序算法(四)--快速排序
数据结构·算法·排序算法
一直学习永不止步4 小时前
LeetCode题练习与总结:最长回文串--409
java·数据结构·算法·leetcode·字符串·贪心·哈希表