分析:
注意,一个矩阵可能没有鞍点,但是如果存在鞍点,鞍点是唯一的吗?
可以证明:一个矩阵中如果存在多个鞍点,则这些鞍点的值是相等的,且位于同一行或同一列
在本题中,用一个5×5的二维数组a存储一个4×4的矩阵(从第1行、第1列开始存储),另外,用第0行存储各列的最小值,用第0列存储各行的最大值,假设输入矩阵如图4(a)所示,则经过计算后,第0行和第0列的取值如图4(b)所示。然后遍历二维数组,如果某个元素a[i][j]的值与a[i][0]值相等,同时也与a[0][j]相等,则a[i][j]就是一个鞍点
反证法:假设一个矩阵中存在多个鞍点,且鞍点的值不一样,例如在图(a)中,假设“*”号所处位置为2个值不一样的鞍点。对(2,2)位置上的鞍点,设为61,它必须是第2行最大的,所以我们尝试着在第2行其他位置上放一些比61小的数,如图(b)所示,61还必须是第2列最小的,因此我们尝试着在第2列其他位置上放一些比61大的数。对(3,4)位置上的鞍点,设为97,它必须是第3行最大的,这可以做到,我们在第3行其他位置放置一些比97小的数,但要保证(3,2)位置上的数处比61大。但是接下来我们无法使得97在第4列是最小的,因为(2,4)这个位置上的数(目前是13)要比61小,肯定比97小,这就矛盾了
同样,假设(3,4)位置上的鞍点比61小,也会导致矛盾。因此,鞍点如果存在多个,则鞍点的值必须是相等的
采用类似的方法,还可以证明:矩阵中如果存在多个鞍点(值是一样的),这些鞍点还必须位于同一行或同一列
本题的关键是求出第j列的最小值(j=1,2,3,4)和第i行的最大值(i=1,2,3,4)。求第j列的最小值的方法如下:先将a[1][j]赋值给变量mn,然后用for循环依次将a[2][j]、a[3][j]、a[4][j]与mn比较并取最小值,最后将mn的值赋值给a[0][j],如下图(a)所示;求第i行的最大值的方法类似,如下图(b)所示
题目要求,如果存在鞍点,则依次输出每个鞍点,否则(即不存在鞍点)输出no saddle,这需要通过状态变量来实现:定义状态变量flag,约定flag取值为false表示没有鞍点,取值为true表示有鞍点;初值为false;只要找到鞍点就将flag的值改为true最后如果flag的值仍然为false,就表示不存在鞍点
#include<iostream>
using namespace std;
int main(){
//第0行,a[0][1], a[0][2], a[0][3], a[0][4]
//第0列,a[1][0], a[2][0], a[3][0], a[4][0]
int a[5][5], i, j;
for(i=1;i<5;i++){
for(j=1;j<5;j++)
cin >> a[i][j];
}
for(j=1;j<5;j++){ //求每一列的最小值
int mn = a[1][j];
for(i=2;i<5;i++){
if(a[i][j]<mn)
mn = a[i][j];
}
a[0][j] = mn;
}
for(i=1;i<5;i++){ //求每一行的最大值
int mx = a[i][1];
for(j=2;j<5;j++){
if(a[i][j]>mx)
mx = a[i][j];
a[i][0] = mx;
}
a[i][0] = mx;
}
bool flag = false; //是否存在鞍点的状态变量
for(i=1;i<5;i++){
for(j=1;j<=5;j++){
if(a[i][j]==a[i][0] and a[i][j]==a[0][j]){
cout << a[i][j] << " " << i << " " << j << endl;
flag = true;
}
}
}
if(flag==false) cout << "no saddle" << endl;
return 0;
}