案例八:求一个矩阵中的鞍点

分析:

注意,一个矩阵可能没有鞍点,但是如果存在鞍点,鞍点是唯一的吗
可以证明:一个矩阵中如果存在多个鞍点,则这些鞍点的值是相等的且位于同一行或同一列 

在本题中,用一个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;
}
  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
矩阵的马鞍点是指在矩阵某个元素在其所在行最小,而在其所在列最大的元素。如果一个矩阵存在马鞍点,那么这个点就是唯一的。 我们可以通过遍历矩阵,找到每一行的最小元素和每一列的最大元素,然后判断是否存在一个元素既是最小值又是最大值。如果存在这样的元素,则它就是矩阵的马鞍点。 下面是一个用 C++ 实现的示例代码: ```cpp #include <iostream> using namespace std; const int N = 110; int main() { int a[N][N]; int n, m; cin >> n >> m; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) cin >> a[i][j]; bool found = false; for (int i = 0; i < n; i++) { int min_val = a[i][0], min_j = 0; for (int j = 1; j < m; j++) if (a[i][j] < min_val) { min_val = a[i][j]; min_j = j; } bool is_saddle = true; for (int k = 0; k < n; k++) if (a[k][min_j] > min_val) { is_saddle = false; break; } if (is_saddle) { cout << "Saddle point found at (" << i << ", " << min_j << "): " << min_val << endl; found = true; break; } } if (!found) cout << "No saddle point found." << endl; return 0; } ``` 这里我们用了两层循环,第一层循环遍历每一行,第二层循环遍历每一列。在第一层循环,我们找到当前行的最小值和对应的列号,然后在第二层循环判断这个最小值是否是其所在列的最大值,如果是,则找到了矩阵的马鞍点。如果没有找到,则输出“No saddle point found.”。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值