习题7-5 找鞍点

一个矩阵元素的“鞍点”是指该位置上的元素值在该行上最大、在该列上最小。

本题要求编写程序,求一个给定的n阶方阵的鞍点。

输入格式:

输入第一行给出一个正整数n(1)。随后n行,每行给出n个整数,其间以空格分隔。

输出格式:

输出在一行中按照“行下标 列下标”(下标从0开始)的格式输出鞍点的位置。如果鞍点不存在,则输出“NONE”。题目保证给出的矩阵至多存在一个鞍点。

输入样例1:

4
1 7 4 1
4 8 3 6
1 6 1 2
0 7 8 9
 

输出样例1:

2 1
 

输入样例2:

2
1 7
4 1
 

输出样例2:

NONE

先把代码放出来:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
int main() {
    int n = 0;
    scanf("%d", &n);
    int** a = NULL;
    a = (int**)malloc(n * sizeof(int*));
    for (int i = 0; i < n; i++) {
        a[i] = (int*)malloc(n * sizeof(int));
        for (int j = 0; j < n; j++) {
            scanf("%d", &a[i][j]);
        }
    }


    int* x = NULL;
    int* y = NULL;
    x = (int*)malloc(n * sizeof(int));
    y = (int*)malloc(n * sizeof(int));


    int linemax = 0, lineone = a[0][0];
    int verticalmax = 0, verticalone = a[0][0];


    for (int i = 0; i < n; i++) {
        linemax = a[i][0];
        verticalmax = a[0][i];
        for (int j = 0; j < n; j++) {
            if (linemax < a[i][j]) {
                linemax = a[i][j];
            }
        }
        x[i] = linemax;


        for (int j = 0; j < n; j++) {
            if (verticalmax > a[j][i]) {
                verticalmax = a[j][i];
                verticalone = i;
            }
        }
        y[i] = verticalmax;
    }


    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (x[i] == y[j]) {
                printf("%d %d", i, j);
                return 0;
            }
        }
    }

    printf("NONE");
    return 0;
}

先分析下代码吧,这个题我费了老大劲了,太头疼了。(俺太难啦!太愚笨了)

1.我的思路是,通过二维动态数组把整个矩阵存起来;(二维数组可以稍微了解以下)

2.然后定义存放横最大值的linemax,和纵最大值的verticalmax。2个动态数组,分别用来存放横和纵。(横:line   纵:vertical)

3.一个大的for用来循环次数,里面有2个小的for,第一个是横的最大值,然后存放到a[]中,同理第二个for,存到b[]中。

4.大的循环结束后,用循环来判断两个数组(x和y)有没有相同元素,如果有,直接输出并且结束主函数;如果没有,一直结束,最后输出NONE,并且结束主函数。

可能有的地方大家不太懂,我就用大白话说了,我觉得比较不太懂的地方就是中间的for循环和最后的一个for循环。

核心思路:题目要求每排的最大值,每列的最小值,并且是同一个位置,我们就可以根据此条有效信息来做核心代码。

x数组是每排的最大值,就按题目列举的数据来看,x[0]=7,x[1]=8,x[2]=6,x[3]=9

y数组是每排的最小值,y[0]=0,y[1]=6,y[2]=1,y[3]=1

7  8  6  9  

0  6  1  1

可以看出,上方的6和下方的6是相同的,然后6在上方的位置是2,下方的位置是1(从0开始)

所以最后输出2  1

写写这个题目的心得吧,能写出来真的挺不容易的,我最初的思路是在线处理,希望通过键盘键入,然后保存到临时变量里面去,并且在每一行输入结束后,都可以记录到数组中,然后进行判断。可是想着想着发现了漏洞,那就是每一列的最小值该怎么比较出来呢,我想了很多办法,奈何俺行列式不太牛,就放弃了,照着这个思路继续的话,还要再写一个循环,那么在线处理的意义是什么呢,不就又要浪费大量的资源了,所以就放弃了第一个想法。

第二个思路是,通过大的for循环,中间的2个小循环,直接比较出来,如果符合条件,就直接在大的循环里面(小的循环外边)输出并且退出(因为题目说最多只有一个鞍点)。然后我就写鸭写,发现做不出来,原因是:最外层的 i 是累加的,第一个小的for循环可以比较出来第一行的最大值,然后就存到临时变量里面去,第二个for循环比较出来第一列的一个最小值,存到另一个临时变量里面去,然后比较是否相等,如果相等就输出,不相等就继续循环直至结束为止。  这个思路最大的漏洞是,第一次大的循环是判断第一行和第一列,第二次大的循环是判断第二行和第二列,这和本题的要求不一样!题目要求是,可能第一行的最大值和第二列的最小值相等;这种情况以上思路无论怎么改进也没有办法修正。只能放弃。

最终就是代码思路,我觉得可以更加精进,比如一半在线处理,当键盘键入时,可以将x[]数组填满,但是还需要2重循环来处理y[](俺不会在线处理y,如果有大佬会,请指教),然后在处理y的循环中判断,如果发现符合条件的,可以直接输出。直至结束。

兄弟们加油。哪里有问题请指正。

原文地址:https://www.cnblogs.com/KeithTee/p/13829345.html