P1719 最大加权矩形 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
二位前缀和的思路,我们使用二维前缀和来预处理,只有开四个for循环来枚举矩形的左起点和右下方的点。来求,时间复杂度达到10的8次方维230
-
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.io.PrintWriter;
- import java.math.BigInteger;
- import java.math.MathContext;
- import java.security.PublicKey;
- import java.sql.SQLIntegrityConstraintViolationException;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.Collections;
- import java.util.Comparator;
- import java.util.Iterator;
- import java.util.LinkedList;
- import java.util.Objects;
- import java.util.PriorityQueue;
- import java.util.Scanner;
- import java.util.TreeMap;
- import java.util.TreeSet;
- public class Main {
- public static void main(String[] args) throws NumberFormatException, IOException {
- Scanner sc=new Scanner(System.in);
- BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
- PrintWriter pw1=new PrintWriter(System.out);
- //String[] aStrings=br.readLine().split(" ");
- aa=sc.nextInt();
- bb=new int[aa+1][aa+1];
- pre=new int[aa+1][aa+1];
- int a;
- int b;
- for(a=1;a<=aa;a++) {
- for(b=1;b<=aa;b++) {
- bb[a][b]=sc.nextInt();
- }
- }
- for(a=1;a<=aa;a++) {
-
- for(b=1;b<=aa;b++) {
- pre[a][b]=pre[a-1][b]+pre[a][b-1]+bb[a][b]-pre[a-1][b-1];
- // System.out.println("A"+pre[a][b]);
- }
- }
- int c;
- int d;
- int answer=0;
- for(a=1;a<=aa;a++) {
- for(b=1;b<=aa;b++) {
- for(c=a;c<=aa;c++) {
- for(d=b;d<=aa;d++) {
- answer=Math.max(answer, pre[c][d]-pre[a-1][d]-pre[c][b-1]+pre[a-1][b-1]);
- }
- }
- }
- }
- System.out.println(answer);
- }
- public static int aa;
- public static int[][] bb;
- public static int[][] pre;
- }
毫秒
我们首先来看一n*1的矩形来求最大加权矩形,不难发现这就是求最大子段之和。
有状态转移方程d[e]=Math.max(d[e-1]+c, c);
那么扩展到二位矩形怎么半,
我们可以将n*n的矩形进行压缩,怎么压缩?
举个例子
3 3 3 3
3 3 3 3
1 2 3 4
5 6 3 4
这是4*4的矩形,我们从第二行第二列开始取到第四行第四列为止。
是 3 3 3
2 3 4
6 3 4
我们压缩,压缩为一行有11 9 11然后按照一维的矩形来做即可
那么关键有了,怎么预处理压缩,使用到preaa[a][b]=preaa[a-1][b]+preaa[a][b];
然后我们枚举上界和下界。之后枚举第几列,这样将压缩后的值直接按照最长子段来求即可
-
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.io.PrintWriter;
- import java.math.BigInteger;
- import java.math.MathContext;
- import java.security.PublicKey;
- import java.sql.SQLIntegrityConstraintViolationException;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.Collections;
- import java.util.Comparator;
- import java.util.Iterator;
- import java.util.LinkedList;
- import java.util.Objects;
- import java.util.PriorityQueue;
- import java.util.Scanner;
- import java.util.TreeMap;
- import java.util.TreeSet;
- public class Main {
- public static void main(String[] args) throws NumberFormatException, IOException {
- Scanner sc=new Scanner(System.in);
- BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
- PrintWriter pw1=new PrintWriter(System.out);
- //String[] aStrings=br.readLine().split(" ");
- aa=sc.nextInt();
- preaa=new int[aa+1][aa+1];
- int a;
- int b;
- for(a=1;a<=aa;a++) {
- for(b=1;b<=aa;b++) {
- preaa[a][b]=sc.nextInt();
- preaa[a][b]=preaa[a-1][b]+preaa[a][b]//按列预处理
- }
- }
- int answer=0;
- for(a=1;a<=aa;a++) {//枚举列的上界
- for(b=a;b<=aa;b++) {//枚举列的的下界
- int c=0;//记录压缩后的序列的每个值
- int[] d=new int[aa+1];
- for(int e=1;e<=aa;e++) {
- c=preaa[b][e]-preaa[a-1][e];
- d[e]=Math.max(d[e-1]+c, c);//求出前n个连续数值的的最长数值和
- answer=Math.max(answer, d[e]);//取最大值
- }
- }
- }
- System.out.println(answer);
- }
- public static int aa;
- public static int[][] preaa;
- }