题目描述
给一个矩阵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;
}