题目
给定一个 m×n 的矩阵,寻找这个矩阵的鞍点。鞍点指的是矩阵中的一个元素,它是所在行的最大值,并且是所在列的最小值。例如:在下面的例子中(第 4行第 1 列的元素就是鞍点,值为 8 )。
11 3 5 6 9
12 4 7 8 10
10 5 6 9 11
8 6 4 7 2
15 10 11 20 25
如果存在鞍点,输出鞍点所在的行、列及其值,如果存在多个,先输出行数更小的,行数相同,先输出列数最小的,如果不存在,输出 " No " 。
INPUT
第 1行: 2个数 m,n,对应矩阵的行列数量( 2≤m,n≤100 )
第 2∼n+1行:每行 mm 个数中间用空格分隔( 0≤m(i,j)≤1000 )
OUTPUT
如果存在 t个鞍点,输出共 t行,每行 3个数,对应所在的行、列及其值,如果不存在鞍点,输出 " No"
输入样例
5 5
11 3 5 6 9
12 4 7 8 10
10 5 6 9 11
8 6 4 7 2
15 10 11 20 25
输出样例
4 1 8
下面是常规找鞍点的写法:
int max,min,x,y,flag=0;//这是一个m行n列二维数组a[101][101]
for(i=0;i<m;i++)
{
max=a[i][0];//把每一列的第一个元素看成是最大值
//找第i行的最大值
for(j=0;j<n;j++)
{
if(max<=a[i][j])
{
max=a[i][j];
//记录其下标
x=i;
y=j;
}
}
min=a[x][y];
//判断该点是不是这一列的最小值
for(j=0;j<m;j++)
{
if(min>a[j][y])
{
min=a[j][y];
}
}
if(max==min)//满足条件是鞍点
{
printf("%d %d %d\n",x+1,y+1,a[x][y]);
flag=1;
}
}
if(flag==0)//不满足条件
{
printf("No\n");
}
咱们以前学的找鞍点的思路,都是先按行来找,则先找出这一行里的最大值,记录其下标位置,再判断它是不是这一列的最小值,如果满足条件则该点是鞍点(否则不是鞍点)。重复上述操作,再到下一行找该行的最大值,再执行、再判断。不过有个问题你发现没有,如果说我一行元素值都相同。那阁下又如何用这种方法找到该行的最大值。
当时用上面这种思路解决这道题,一个测试点没过,直接给我整的汗流浃背了。
后来,在经历过n次提交后,终于想到了最原始的方法:对!就是全都遍历一遍(管它超时不超时,都这样了,还要啥自行车,我要重铸原始人荣光)
下面是改进后的代码:
int flag=0;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
int tip=1;
x=i;y=j;
//判断是不是行最大
int ii;
for (ii = 0; ii < n; ii++)
{
if (a[x][ii] > a[x][y])
{
tip = 0;
}
}
//判断是不是列最大
if(tip==1)
{
for (ii = 0; ii < m; ii++)
{
if (a[ii][y] < a[x][y])
{
tip = 0;
}
}
}
if (tip==1)
{
flag = 1;
printf("%d %d %d\n",i+1,j+1,a[i][j]);
}
}
}
if (flag == 0)
{
printf("No\n");
}
用这种把所有点都遍历一遍的方法,虽然慢,但它最少解决上面找最大值难的问题。
完整代码如下:
#include <stdio.h>
int main()
{
int i,j,x,y,m,n;
int a[101][101];
scanf("%d %d",&m,&n);
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
scanf("%d",&a[i][j]);
}
}
int flag=0;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
int tip=1;
x=i;y=j;
//判断是不是行最大
int ii;
for (ii = 0; ii < n; ii++)
{
if (a[x][ii] > a[x][y])
{
tip = 0;
}
}
//判断是不是列最大
if(tip==1)
{
for (ii = 0; ii < m; ii++)
{
if (a[ii][y] < a[x][y])
{
tip = 0;
}
}
}
if (tip==1)
{
flag = 1;
printf("%d %d %d\n",i+1,j+1,a[i][j]);
}
}
}
if (flag == 0)
{
printf("No\n");
}
return 0;
}
后面我又加了一个函数seek封装,来判断某一点是不是鞍点,目的是为了让它看起来更简洁一些。
#include <stdio.h>
int a[101][101];
int n, m;
int seek(int, int);
int main()
{
int i,j,x,y;
scanf("%d %d",&m,&n);
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
scanf("%d",&a[i][j]);
}
}
int flag=0;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
int tip=seek(i, j);
if (tip==1)
{
flag = 1;
printf("%d %d %d\n",i+1,j+1,a[i][j]);
}
}
}
if (flag == 0)
{
printf("No\n");
}
return 0;
}
int seek(int x, int y)
{
//判断是不是行最大
int i;
for (i = 0; i < n; i++)
{
if (a[x][i] > a[x][y])
{
return 0;
}
}
//判断是不是列最大
for (i = 0; i < m; i++)
{
if (a[i][y] < a[x][y])
{
return 0;
}
}
return 1;
}