Acwing 4863. 构造新矩阵 (二分) java
🤠 原题地址
🤠 核心思路:二分
import java.util.*;
public class Main
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
while (T-- > 0)
{
// 输入数据
int m = sc.nextInt(), n = sc.nextInt();// m 是行 n 是列
int[][] a = new int[m][n];
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
a[i][j] = sc.nextInt();
}
// 分情况而论
if (m <= n - 1)// 当行数m <= n-1 时,也就是每一行都可以选
{
int ans = 1000_000_000;// 下划线仅仅是为了易辨识,无其他作用
for (int i = 0; i < n; i++)
{
int max = 0;// 列最大值
for (int j = 0; j < m; j++)
{// 枚举每一列的每一个数
max = Math.max(max, a[j][i]);// 找出每一列中的最大值
}
ans = Math.min(ans, max);// 找出所有列最大值中的最小值
}
System.out.println(ans);
} else// 并不能选择所有行,所以得想办法选到每一列的最大值那行
{
int l = 0, r = 1000_000_000;
int[] x = new int[m];// 记录第 n 行上的大于 结果的 值的个数(即可以求出某一行上有两个列最大值的)
while (l <= r)
{
boolean ok = true;// 记录这个结果 mid 是否合法
boolean f = false;// 记录是否有一行上有两个列最大值的情况
int mid = l + r >> 1;// 假设 mid 是答案
for (int i = 0; i < n && ok; i++)// 枚举每一列
{
boolean ff = false;// 记录这一列有无不小于 结果mid 的数
for (int j = 0; j < m; j++)// 枚举每一列上的每一个元素
{
if (a[j][i] >= mid)
{
x[j]++;// 行上的最大值 +1 (假设mid是最优答案的)
ff = true;// 这一列符合选取 mid 为结果的情况
}
}
// 某一列不符合选取 mid 为结果
if (!ff)
{
ok = false;// mid 不合法
}
}
for (int i = 0; i < m; i++)
{
// 遍历每一行上的列最大值个数,判断是否能找到一行上有两个列最大值的情况
if (x[i] >= 2)
f = true;
}
if (ok && f)// mid 合法并且至少有一行上有两个列最大值
{
l = mid + 1;
} else
{
r = mid - 1;
}
Arrays.fill(x, 0);
}
System.out.println(r);
}
}
}
}

浙公网安备 33010602011771号