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);
			}
		}
	}
}
posted @ 2023-02-18 23:19  兑生  阅读(23)  评论(0)    收藏  举报  来源
Live2D