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;
}
相关推荐
劲夫学编程39 分钟前
leetcode:杨辉三角
算法·leetcode·职场和发展
毕竟秋山澪41 分钟前
孤岛的总面积(Dfs C#
算法·深度优先
浮生如梦_3 小时前
Halcon基于laws纹理特征的SVM分类
图像处理·人工智能·算法·支持向量机·计算机视觉·分类·视觉检测
励志成为嵌入式工程师5 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉5 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer5 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
wheeldown6 小时前
【数据结构】选择排序
数据结构·算法·排序算法
观音山保我别报错7 小时前
C语言扫雷小游戏
c语言·开发语言·算法
TangKenny8 小时前
计算网络信号
java·算法·华为
景鹤8 小时前
【算法】递归+深搜:814.二叉树剪枝
算法