算法训练 采油区域

ALGO-44 采油区域

资源限制

时间限制:2.0s 内存限制:512.0MB

问题描述

采油区域  Siruseri政府决定将石油资源丰富的Navalur省的土地拍卖给私人承包商以建立油井。被拍卖的整块土地为一个矩形区域,被划分为M×N个小块。
Siruseri地质调查局有关于Navalur土地石油储量的估测数据。这些数据表示为M×N个非负整数,即对每一小块土地石油储量的估计值。
为了避免出现垄断,政府规定每一个承包商只能承包一个由K×K块相连的土地构成的正方形区域。AoE石油联合公司由三个承包商组成,他们想选择三块互不相交的K×K的区域使得总的收益最大。
例如,假设石油储量的估计值如下:

111111111
111111111
188888111
188888111
188888111
111188811
111111888
111111999
111111999

如果K = 2, AoE公司可以承包的区域的石油储量总和为100, 如果K = 3, AoE公司可以承包的区域的石油储量总和为208。
AoE公司雇佣你来写一个程序,帮助计算出他们可以承包的区域的石油储量之和的最大值。

输入格式

输入第一行包含三个整数M, N, K,其中M和N是矩形区域的行数和列数,K是每一个承包商承包的正方形的大小(边长的块数)。接下来M行,每行有N个非负整数表示这一行每一小块土地的石油储量的估计值。

输出格式

输出只包含一个整数,表示AoE公司可以承包的区域的石油储量之和的最大值。

测试样例

输入:
9 9 3
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 8 8 8 8 8 1 1 1
1 8 8 8 8 8 1 1 1
1 8 8 8 8 8 1 1 1
1 1 1 1 8 8 8 1 1
1 1 1 1 1 1 8 8 8
1 1 1 1 1 1 9 9 9
1 1 1 1 1 1 9 9 9

输出:
208

数据规模与约定

数据保证K≤M且K≤N并且至少有三个K×K的互不相交的正方形区域。其中30%的输入数据,M, N≤ 12。所有的输入数据, M, N≤ 1500。每一小块土地的石油储量的估计值是非负整数且≤ 500。

AC code:

import java.io.*;
import java.util.*;

public class Main {

    public static void main(String[] args) {
        InputReader in = new InputReader(System.in, " \n");
        int m = in.nextInt(), n = in.nextInt(), k = in.nextInt(), k2 = k + k, res = 0;
        int[][] map = new int[m + 1][n + 1],
                TL = new int[m + 2][n + 2],
                TR = new int[m + 2][n + 2],
                BR = new int[m + 2][n + 2],
                BL = new int[m + 2][n + 2];
        for (int i = 1; i <= m; i++)
            for (int j = 1; j <= n; j++) map[i][j] = map[i - 1][j] + map[i][j - 1] - map[i - 1][j - 1] + in.nextInt();
        for (int i = m; i >= k; i--)
            for (int j = n; j >= k; j--) map[i][j] -= map[i - k][j]  + map[i][j - k] - map[i - k][j - k];
        for (int i = k; i <= m; i++) for (int j = k; j <= n; j++) TL[i][j] = max(map[i][j], max(TL[i][j - 1], TL[i - 1][j]));
        for (int i = k; i <= m; i++) for (int j = n; j >= k; j--) TR[i][j] = max(map[i][j], max(TR[i][j + 1], TR[i - 1][j]));
        for (int i = m; i >= k; i--) for (int j = n; j >= k; j--) BR[i][j] = max(map[i][j], max(BR[i][j + 1], BR[i + 1][j]));
        for (int i = m; i >= k; i--) for (int j = k; j <= n; j++) BL[i][j] = max(map[i][j], max(BL[i][j - 1], BL[i + 1][j]));
        for (int i = k2; i <= m; i++)
            for (int j = k2; j <= n; j++)
                res = max(TL[i - k][j - k] + TR[i - k][j] + BL[i][n],
                        TL[i - k][j - k] + TR[m][j] + BL[i][j - k],
                        TL[i - k][n] + BL[i][j - k] + BR[i][j],
                        TL[m][j - k] + TR[i - k][j] + BR[i][j], res);
        for (int j = k2, q = n - k, max = 0; j <= q; res = max(res, max + TL[m][j - k] + TR[m][j + k]), max = 0, j++)
            for (int i = k, p = m - k; i <= p; i++) if (map[i][j] > max) max = map[i][j];
        for (int i = k2, l = m - k, max = 0; i <= l; res = max(res, max + TL[i - k][n] + BL[i + k][n]), max = 0, i++)
            for (int j = k; j <= n; j++) if (map[i][j] > max) max = map[i][j];
        System.out.print(res);
    }

    static int max(int var1, int var2) { return var1 > var2? var1: var2; };

    static int max(int var1, int var2, int var3, int var4, int var5) { return max(var1, max(var2, max(var3, max(var4, var5)))); };

    static class InputReader {

        BufferedReader read;
        StringTokenizer token;
        String delimiters;

        InputReader(InputStream in) { this(in, " \t\n\r\f"); }

        InputReader(InputStream in, String delimiters) {
            this.read = new BufferedReader(new InputStreamReader(in));
            this.token = new StringTokenizer("", this.delimiters = delimiters);
        }

        String next() {
            while (!token.hasMoreTokens())
                try {
                    this.token = new StringTokenizer(read.readLine(), delimiters);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            return token.nextToken();
        }

        int nextInt() { return Integer.parseInt(next()); }
    }
}

思路参考
图一画,这题就很明了了
HTML画的
递推出拆分部分在 左上、右上、右下、左下 的最大值
再进行枚举
最后特殊处理一下 #5、#6 这两个用例

调试了半天,比赛要是出这种题,我怎么来的怎么回去

用例10: 8.11 MB,我本以为Java必不过,精了
在这里插入图片描述


before
没头绪,先整手暴搜:

import java.io.*;
import java.util.*;

public class Main {

    static int map[][], x1, y1, x2, y2, K, M, N, max;

    public static void main(String[] args) {
        InputReader in = new InputReader(System.in);
        M = in.nextInt(); N = in.nextInt(); K = in.nextInt();
        map = new int[M + 1][N + 1];
        for (int i = 1; i <= M; i++)
            for (int j = 1; j <= N; j++) map[i][j] = map[i][j - 1] + map[i - 1][j] - map[i - 1][j - 1] + in.nextInt();
        for (int i = M; i >= K; i--)
            for (int j = N; j >= K; j--) map[i][j] -= map[i][j - K] + map[i - K][j] - map[i - K][j - K];
        full(0);
        System.out.print(max);
    }

    static void full(int step) {
        for (int i = K; i <= M; i++)
            for (int j = K; j <= N; j++) {
                if (noPut(i, j)) continue;
                switch (step) {
                    case 0: x1 = i; y1 = j; full(1); x1 = 0; break;
                    case 1: x2 = i; y2 = j; full(2); x2 = 0; break;
                    default: max = max(max, map[x1][y1] + map[x2][y2] + map[i][j]);
                }
            }
    }

    static boolean noPut(int x, int y) {
        if (x1 > 0 && abs(x1 - x) < K && abs(y1 - y) < K) return true;
        if (x2 > 0 && abs(x2 - x) < K && abs(y2 - y) < K) return true;
        return false;
    }

    public static int abs(int var) { return var < 0? -var: var; }

    public static int max(int var1, int var2) { return var1 > var2? var1: var2; }

    static class InputReader {

        BufferedReader read;
        StringTokenizer token;
        String delimiters;

        InputReader(InputStream in) { this(in, " \t\n\r\f"); }

        InputReader(InputStream in, String delimiters) {
            this.read = new BufferedReader(new InputStreamReader(in));
            this.token = new StringTokenizer("", this.delimiters = delimiters);
        }

        String next() {
            while (!token.hasMoreTokens())
                try {
                    this.token = new StringTokenizer(read.readLine(), delimiters);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            return token.nextToken();
        }

        int nextInt() { return Integer.parseInt(next()); }
    }
}

在这里插入图片描述
30分,已经很可以了

朋友叫我出去玩了,回家再做研究

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值