以下三题都采用了悬线法的思想,套模板就行
题目描述
这片土地被分成 N\times MN×M 个格子,每个格子里写着 ‘R’ 或者 ‘F’,R 代表这块土地被赐予了 rainbow,F 代表这块土地被赐予了 freda。
现在 freda 要在这里卖萌。。。它要找一块矩形土地,要求这片土地都标着 ‘F’ 并且面积最大。
但是 rainbow 和 freda 的 OI 水平都弱爆了,找不出这块土地,而蓝兔也想看 freda 卖萌(她显然是不会编程的……),所以它们决定,如果你找到的土地面积为 SS,它们每人给你 SS 两银子。
输入格式
第一行两个整数 NN,MM,表示矩形土地有 NN 行 MM 列。
接下来 NN 行,每行 MM 个用空格隔开的字符 ‘F’ 或 ‘R’,描述了矩形土地。
输出格式
输出一个整数,表示你能得到多少银子,即 (3\times \text{最大 ‘F’ 矩形土地面积}3×最大 ’F’ 矩形土地面积) 的值。
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int[][] map = new int[n+1][m+1];
int[][] l = new int[n+1][m+1];
int[][] r = new int[n+1][m+1];
int[][] up = new int[n+1][m+1];
int ans = 0;
sc.nextLine();
for(int i = 1;i<=n;i++){
String[] s = sc.nextLine().split(" ");
for(int j = 1;j<=m;j++){
if(s[j-1].equals("F")){
map[i][j] = 1;
}else{
map[i][j] = 2;
}
}
}
for(int i = 1;i<=n;i++){
for(int j = 1;j<=m;j++){
l[i][j] = r[i][j] = j;
up[i][j] = 1;
}
}
for(int i = 1;i<=n;i++){
for(int j = 2;j<=m;j++){
if(map[i][j] == map[i][j-1] && map[i][j] == 1){
l[i][j] = l[i][j-1];
}
}
}
for(int i = 1;i<=n;i++){
for(int j = m-1;j>=1;j--){
if(map[i][j] == map[i][j+1] && map[i][j] == 1){
r[i][j] = r[i][j+1];
}
}
}
for(int i = 1;i<=n;i++){
for(int j = 1;j<=m;j++){
if(i > 1){
if(map[i][j] == map[i-1][j] && map[i][j] == 1){
l[i][j] = Math.max(l[i][j],l[i-1][j]);
r[i][j] = Math.min(r[i][j],r[i-1][j]);
up[i][j] = up[i-1][j] + 1;
}
}
int a = r[i][j] - l[i][j] + 1;//极大子矩形的宽
ans = Math.max(a*up[i][j],ans);//最大子矩形的面积
}
}
System.out.println(ans*3);
}
}
题目描述
农夫约翰想要在他的正方形农场上建造一座正方形大牛棚。他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方。我们假定,他的农场划分成 N x N 的方格。输入数据中包括有树的方格的列表。你的任务是计算并输出,在他的农场中,不需要砍树却能够修建的最大正方形牛棚。牛棚的边必须和水平轴或者垂直轴平行。
EXAMPLE
考虑下面的方格,它表示农夫约翰的农场,‘.'表示没有树的方格,‘#'表示有树的方格
1 2 3 4 5 6 7 8
1 . . . . . . . .
2 . # . . . # . .
3 . . . . . . . .
4 . . . . . . . .
5 . . . . . . . .
6 . . # . . . . .
7 . . . . . . . .
8 . . . . . . . .
最大的牛棚是 5 x 5 的,可以建造在方格右下角的两个位置其中一个。
输入格式
Line 1: 两个整数: N (1 <= N <= 1000),农场的大小,和 T (1 <= T <= 10,000)有树的方格的数量
Lines 2…T+1: 两个整数(1 <= 整数 <= N), 有树格子的横纵坐标
输出格式
只由一行组成,约翰的牛棚的最大边长。
package wttwtw;/**
* @author by xxz
* @date 2022/3/29
*/
import java.util.Arrays;
import java.util.Scanner;
/**
* @Description
* @author by xxz
* @date 2022/3/29
* @throws
*/
public class xuan {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int t = sc.nextInt();
int[][] map = new int[n+1][n+1];
int[][] l = new int[n+1][n+1];
int[][] r = new int[n+1][n+1];
int[][] up = new int[n+1][n+1];
int ans = 0;
for(int i = 1;i<=n;i++){
for(int j = 1;j<=n;j++){
map[i][j] = 1;
}
}
for(int i = 0;i<t;i++){
int a = sc.nextInt();
int b = sc.nextInt();
map[a][b] = 2;//2表示障碍
}
for(int i = 1;i<=n;i++){
for(int j = 1;j<=n;j++){
l[i][j] = r[i][j] = j;
up[i][j] = 1;
}
}
for(int i = 1;i<=n;i++){
for(int j = 2;j<=n;j++){
if(map[i][j] == map[i][j-1] && map[i][j] == 1){
l[i][j] = l[i][j-1];
}
}
}
for(int i = 1;i<=n;i++){
for(int j = n-1;j>=1;j--){
if(map[i][j] == map[i][j+1] && map[i][j] == 1){
r[i][j] = r[i][j+1];
}
}
}
for(int i = 1;i<=n;i++){
for(int j = 1;j<=n;j++){
if(i > 1){
if(map[i][j] == map[i-1][j] && map[i][j] == 1){
l[i][j] = Math.max(l[i][j],l[i-1][j]);
r[i][j] = Math.min(r[i][j],r[i-1][j]);
up[i][j] = up[i-1][j] + 1;
}
}
int a = r[i][j] - l[i][j] + 1;//极大子矩形的宽
int b = Math.min(a,up[i][j]);//极大子正方形的边长
ans = Math.max(b,ans);//最大子正方形的边长
}
}
System.out.println(ans);
}
}
小Q找到了一张由N×M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种颜色之一。小Q想在这种纸中裁减一部分作为新棋盘,当然,他希望这个棋盘尽可能的大。
不过小Q还没有决定是找一个正方形的棋盘还是一个矩形的棋盘(当然,不管哪种,棋盘必须都黑白相间,即相邻的格子不同色),所以他希望可以找到最大的正方形棋盘面积和最大的矩形棋盘面积,从而决定哪个更好一些。
输入格式
包含两个整数N和M,分别表示矩形纸片的长和宽。接下来的N行包含一个N ×M的01矩阵,表示这张矩形纸片的颜色(0表示白色,1表示黑色)。
输出格式
包含两行,每行包含一个整数。第一行为可以找到的最大正方形棋盘的面积,第二行为可以找到的最大矩形棋盘的面积(注意正方形和矩形是可以相交或者包含的)。
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int[][] map = new int[n+1][m+1];
int[][] l = new int[n+1][m+1];
int[][] r = new int[n+1][m+1];
int[][] up = new int[n+1][m+1];
int ans = 0;
int res = 0;
for(int i = 1;i<=n;i++){
for(int j = 1;j<=m;j++){
map[i][j] = sc.nextInt();
}
}
for(int i = 1;i<=n;i++){
for(int j = 1;j<=m;j++){
l[i][j] = r[i][j] = j;
up[i][j] = 1;
}
}
for(int i = 1;i<=n;i++){
for(int j = 2;j<=m;j++){
if(map[i][j] != map[i][j-1]){
l[i][j] = l[i][j-1];
}
}
}
for(int i = 1;i<=n;i++){
for(int j = m-1;j>=1;j--){
if(map[i][j] != map[i][j+1]){
r[i][j] = r[i][j+1];
}
}
}
for(int i = 1;i<=n;i++){
for(int j = 1;j<=m;j++){
if(i > 1){
if(map[i][j] != map[i-1][j]){
l[i][j] = Math.max(l[i][j],l[i-1][j]);
r[i][j] = Math.min(r[i][j],r[i-1][j]);
up[i][j] = up[i-1][j] + 1;
}
}
int a = r[i][j] - l[i][j] + 1;//极大子矩形的宽
int b = Math.min(a,up[i][j]);//极大子正方形的边长
ans = Math.max(a*up[i][j],ans);//最大子矩形的面积
res = Math.max(b*b,res);//最大子正方形的面积
}
}
System.out.println(res);
System.out.println(ans);
}
}