程序设计入门C语言 --- 鞍点

题目内容:

给定一个n*n矩阵A。矩阵A的鞍点是一个位置(i,j),在该位置上的元素是第i行上的最大数,第j列上的最小数。一个矩阵A也可能没有鞍点。

你的任务是找出A的鞍点。

输入格式:

输入的第1行是一个正整数n, (1<=n<=100),然后有n行,每一行有n个整数,同一行上两个整数之间有一个或多个空格。

输出格式:

对输入的矩阵,如果找到鞍点,就输出其下标。下标为两个数字,第一个数字是行号,第二个数字是列号,均从0开始计数。

如果找不到,就输出

NO

题目所给的数据保证了不会出现多个鞍点。

输入样例:

1 7 4 1 

4 8 3 6 

1 6 1 2 

0 7 8 9

输出样例:

2 1

时间限制:500ms内存限制:32000kb


思路一:

1.找出每行中最大的数字,记录其列的下标

2.再判断其在对应的列上是否为最小值

代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//思路一 
int main()
{
        const int max = 100;
	int a[max][max] = { 0 };
	int n = 4;
	scanf("%d", &n);
	//初始化
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			scanf("%d", &a[i][j]);
		}

	}
	//每行找最大
	int i = 0;
	int j = 0;
	for ( i = 0; i < n; i++)
	{
		int max = a[i][0];//默认每行的第一个数字为最大
		int locy = 0;//记录最大数所在的列
		int locx = 0;//记录最大数所在的行
		for (j = 1; j < n; j++)
		{
			if (a[i][j]>max)
			{
				max = a[i][j];
				locy = j;
				locx = i;
			}
		}
	//找到对应最大的数字后,检查该列,判断在该列是否为最小
	    int min = max;
	    //int locx = 0;//保存列中最小数字的横坐标
	    for (int i = 0; i < n; i++)
	    {
	      if (a[i][locy] <min)
	      {
	           min = a[i][locy];
		   locx = i;
	      }
	    }
	   if (max == min)
	   {
	      printf("%d %d\n", locx, locy);
	      break;
	   }
	}
	if (i == n)
	{
	   printf("NO");
	}
  return 0;
}

注意:

:找到每行的最大数字直接检查其对应列就可以了,为什么这段代码中我们看到它在找到每行最大值后还记录了行下标?

答:因为 int min=max;这句。我把每行的最大值默认为它是其所在列的最小值,然后检查该列的每一个数;如果比它小,就更新min的值和min值对应的行数。若只记录列,则当遍历行到a[2][1]=6时,检查对应列,因为在当列中无比6更小的数,所以第41行的if语句就进不去,不会进行locx的更新,这时locx就还是初始值0,最后输出位置[0][1]。

如果 改为int min =a[0][locy];(即把每列的第一个默认为最小数字的话,则找到每行的最大值后不需要记录行下标,只需记录列下标即可)

//每行找最大
	int i = 0;
	int j = 0;
	for ( i = 0; i < n; i++)
	{
		int max = a[i][0];
		int locy = 0;//记录最大数所在的列
		for (j = 1; j < n; j++)
		{
			if (a[i][j]>max)
			{
				max = a[i][j];
				locy = j;
			}
		}
	//找到对应最大的数字后,检查该列,判断在该列是否为最小
            int min =a[0][locy];//默认每列中第一个数为最小值
	    int locx = 0;//保存列中最小数字的横坐标
	    for (int i = 1; i < n; i++)
	    {
	      if (a[i][locy] <min)
	      {
	             min = a[i][locy];
		     locx = i;
	      }
	    }
	   if (max == min)
	   {
	      printf("%d %d\n", locx, locy);
	      break;
	   }
	}
	if (i == n)
	{
	   printf("NO");
	}

思路二:

1.分别建立max与min两个一维数组。max数组存储每行最大值所在的列下标,min数组存储每列最小值所在的行下标

2.遍历max数组,若min[max[i]]=i,则说明找到了鞍点。

图解如下-->

代码:

//思路二
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#define M 100
int main()
{
        const int Max = 100;
	int a[Max][Max] = { 0 };
	int n = 0;
	scanf("%d", &n);
	//初始化
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			scanf("%d", &a[i][j]);
		}
	}
	int max[M] = { 0 };//找每行中的最大数,存列下标
	int min[M] = { 0 };//找每列中的最小数,存行下标
	int flag = 0;//标志位,为0则代表没有找到,为1代表找到鞍点
	int i = 0;
	int j = 0;
	//寻找每行的最大值,把列下标存入max数组
	for (i = 0; i < n; i++)
	{
		int big = a[i][0];
		for ( j = 1; j < n; j++)
		{
			if (a[i][j]>big)
			{
				max[i] = j;
				big = a[i][j];
			}
		}
	}
	//寻找每列的最小值,把行下标存入min数组
	for (j = 0; j < n; j++)
	{
		int small = a[0][j];
		for ( i = 1; i < n; i++)
		{
			if (a[i][j] < small)
			{
				min[j] = i;
				small = a[i][j];
			}
		}
	}
	//遍历数组,寻找鞍点
	for ( i = 0; i < n; i++)
	{
		int t = max[i];
		if (min[t] == i)
		{
			flag = 1;
			break;
		}
	}
	if (flag == 1)
	{
		printf("%d %d", i, max[i]);
	}
	else
	{
		printf("NO");
	}
  return 0;
}

说明:由于目前水平不够,本题目代码还是不够完善,没有考虑最大or最小值重复的情况(如下图所示的情况本代码没有办法处理)。编程能力还需提高

猜你喜欢

转载自blog.csdn.net/melody_1016/article/details/81296048