一个矩阵元素的“鞍点”是指该位置上的元素值在该行上最大、在该列上最小。
本题要求编写程序,求一个给定的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的循环中判断,如果发现符合条件的,可以直接输出。直至结束。
兄弟们加油。哪里有问题请指正。