pta题集——找鞍点

一个矩阵元素的“鞍点”是指该位置上的元素值在该行上最大、在该列上最小。

本题要求编写程序,求一个给定的n阶方阵的鞍点。

输入格式:

输入第一行给出一个正整数n(1≤n≤6)。随后n行,每行给出n个整数,其间以空格分隔。

输出格式:

输出在一行中按照“行下标 列下标”(下标从0开始)的格式输出鞍点的位置。如果鞍点不存在,则输出“NONE”。题目保证给出的矩阵至多存在一个鞍点。

题目分析:

一个矩阵元素的“鞍点”是指该位置上的元素值在该行上最大、在该列上最小。

如图所示:

第一个矩阵的鞍点为6,第二个矩阵的鞍点为5,同时要注意第二个矩阵中同一行里有两个相同的最大元素,则要一一进行判断。

解答过程:

数据输入:
n=int(input())
ls=[]
for i in range(n):
    row=list(map(int,input().split()))
    ls.append(row)

读入了正整数n,表示这是一个n*n的矩阵,然后再将矩阵存储进二维列表中。

寻找鞍点及输出部分:
found=0
i=0
while i<n:
    max_num=max(ls[i])
    for j in range(n):
        if ls[i][j]==max_num:
            flag=0
            for k in range(n):
                if ls[k][j]<max_num:
                    flag=1
                    break
            if flag==0:
                print(f"{i} {j}")
                found=1
                break
    if found:
        break
    i+=1
                    
if found==0:
    print("NONE")

定义found变量表示是否找到鞍点

开启循环,遍历矩阵的每行,先找出每行中的最大数字,在遍历此行的过程中,若此行中有元素等于此行的最大数,则将flag置为0(flag用于判断该元素是否为鞍点),记下该元素的列,遍历该元素所在列,若该列中有元素小于该元素,则flag置为1,该元素不是鞍点,跳出此层循环。若遍历完该列后flag仍为0,则该元素为鞍点,输出该元素的横纵坐标,并且将found置为1。

当found为1时,表明鞍点已找到,此时即可跳出while循环。若在while循环结束后found仍为0,则未找到鞍点,输出NONE。

该循环的特色是当一行中存在不止一个最大值时,可以将每个最大值都依次进行判断,而不会遗漏某个最大值。同时这也是flag=0这一行的定义须在当遍历此行的元素时此行的某一元素等于此行的最大值的if语句之下的原因,这样才能保证每一个最大值元素在判断时flag都重新置为0。

总体代码展示:
n=int(input())
ls=[]
for i in range(n):
    row=list(map(int,input().split()))
    ls.append(row)

found=0
i=0
while i<n:
    max_num=max(ls[i])
    for j in range(n):
        if ls[i][j]==max_num:
            flag=0
            for k in range(n):
                if ls[k][j]<max_num:
                    flag=1
                    break
            if flag==0:
                print(f"{i} {j}")
                found=1
                break
    if found:
        break
    i+=1
                    
if found==0:
    print("NONE")

运行测试:

输入样例1:
4
1 7 4 1
4 8 3 6
1 6 1 2
0 7 8 9
输出样例1:
2 1
运行结果:

输入样例2:
2
1 7
4 1
输出样例2:
NONE
运行结果:

 

额外测试样例:
5
9 8 7 6 5
4 7 9 8 3
1 6 2 6 5
3 7 4 8 9
1 9 8 7 0

该测试样例是为了测试当矩阵的同一行或列有相同最大/小值时是否能正确判断

测试结果:

PTA平台上,寻鞍点的基本思路是先出每一行的最大值,再判断该最大值是否为所在列的最小值。以下是几种不同的代码示例: #### 代码示例一 ```c #include <stdio.h> int main() { int i, j, n, temp, temp2, max, min; int a[6][6] = {0}; int flag = 1; scanf("%d", &n); if (n == 1) { printf("0 0"); return 0; } for (i = 0; i < n; i++) for (j = 0; j < n; j++) scanf("%d", &a[i][j]); for (i = 0; i < n; i++) { max = a[i][0]; for (j = 0; j < n; j++) { if (max <= a[i][j]) { max = a[i][j]; temp = j; } } min = a[i][temp]; for (j = 0; j < n; j++) { if (min > a[j][temp]) { min = a[j][temp]; break; } } if (max == min) { flag = 0; printf("%d %d", i, temp); break; } } if (flag) printf("NONE"); return 0; } ``` 此代码先判断矩阵是否为 1x1 的情况,若是则直接输出 `0 0`。对于其他情况,遍历每一行出最大值及其所在列,再检查该最大值是否为所在列的最小值,若是则输出其坐标,若遍历完都未到则输出 `NONE` [^2]。 #### 代码示例二 ```c #include <stdio.h> #pragma warning(disable:4996) int main(void) { int nu[6][6],n,fv=0; scanf("%d", &n); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { scanf("%d", &nu[i][j]); } } for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { int cnt = 0; for (int m = 0; m < n; m++) { if (nu[i][j] >= nu[i][m]) cnt++; } if (cnt == n) { cnt = 0; for (int m = 0; m < n; m++) { if (nu[i][j] <= nu[m][j]) cnt++; } if (cnt == n) { printf("%d %d\n", i, j); fv++; } } } } if (!fv) printf("NONE"); return 0; } ``` 该代码先读取矩阵元素,然后遍历矩阵中的每个元素,对于每个元素,先检查其是否为所在行的最大值,若是则再检查是否为所在列的最小值,若都满足则输出其坐标并标记已鞍点,若最终未到则输出 `NONE` [^3]。 #### 代码示例三 ```c #include<stdio.h> int main() { int a[6][6], i, n, flag = 0, j, k, x, y = 0; scanf("%d", &n); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { scanf("%d", &a[i][j]); } } if (n == 1) { printf("0 0"); } else { for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (a[i][j] >= a[i][y]) { y = j; } } x = i; for (k = 0; k < n; k++) { if (a[k][y] < a[x][y]) { x = k; break; } } if (x == i) { flag = 1; break; } } if (flag) { printf("%d %d", x, y); } else { printf("NONE"); } } return 0; } ``` 此代码同样先处理 1x1 矩阵的情况,对于其他矩阵,遍历每一行出最大值所在列,然后检查该最大值是否为所在列的最小值,若满足则标记已鞍点并输出坐标,未到则输出 `NONE` [^4]。 #### 代码示例四 ```c #include <stdio.h> int main() { int n; scanf("%d",&n); int a[n][n]; int i, j; for(i=0; i<n; i++) { for(j=0; j<n; j++) { scanf("%d",&a[i][j]); } } int k=0,y=0,flag=1,p=0; if(n==1) { printf("0 0"); } else { for(i=0; i<n; i++) { y=i; for(p=0; p<n; p++) { if(a[i][k]<=a[i][p]) { k=p; } } for(j=0; j<n; j++) { if(a[y][k]>a[j][k]) { y=j; break; } } if(i==y) { flag=0; break; } } if(flag==0) printf("%d %d",i,k); else printf("NONE"); } return 0; } ``` 该代码先读取矩阵阶数和元素,对于 1x1 矩阵直接输出坐标,对于其他矩阵,遍历每一行出最大值所在列,再检查该最大值是否为所在列的最小值,若满足则标记并输出坐标,未到则输出 `NONE` [^5]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值