1002. 二哥种花生-java算法

问题

Description

二哥在自己的后花园里种了一些花生,也快到了收获的时候了。这片花生地是一个长度为L、宽度为W的矩形,每个单位面积上花生产量都是独立的。他想知道,对于某个指定的区域大小,在这么大的矩形区域内,花生的产量最大会是多少。

Input Format

第1行有2个整数,长度L和宽度W。

第2行至第L+1行,每行有W个整数,分别表示对应的单位面积上的花生产量A( 0≤A<10)。

第L+2行有2个整数,分别是指定的区域大小的长度a和宽度b。

Output Format

输出一个整数m,表示在指定大小的区域内,花生最大产量为m。

Sample Input

4 5 
1 2 3 4 5 
6 7 8 0 0 
0 9 2 2 3 
3 0 0 0 1 
3 3

Sample Output

38

样例解释

左上角:38 = (1+2+3) + (6+7+8) + (0+9+2)

数据范围

对于30%的数据: 1≤L,W≤100;

对于100%的数据: 1≤L,W≤1000。

全部区域大小满足:1≤a≤L,1≤b≤W。


解答

思路

首先想到的是循环。然后按照矩形存下所有可能的结果,比较大小留最大的即可。这个是最简单的思路。代码如下
  1. import java.util.Scanner;
    
    /**
     * @author by zhouzhigang6 on 2018/2/3.
     */
    public class Main1002 {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int L = sc.nextInt();
            int W = sc.nextInt();
            int[][] s = new int[L][W];
            for (int i = 0; i < L; i++) {
                for (int j = 0; j < W; j++) {
                    s[i][j] = sc.nextInt();
                }
            }
            int result = 0;
            int a = sc.nextInt();
            int b = sc.nextInt();
            int temp = 0;
    
            for (int m = 0; m <= L-a; m++) {
                for (int n = 0; n <= W-b; n++) {
                    //求圈出的面积
                    for (int i = 0; i < a; i++) {
                        for (int j = 0; j < b; j++) {
                            temp += s[i + m][j + n];
                        }
                    }
                    if (result < temp) {
                        result = temp;
                    }
                    temp = 0;
                }
            }
            System.out.println(result);
        }
    }
思路是没错的,也能得到正确结果。可是问题来了,提交时会提示超时。第一反应就是效率太低下,四重循环写法是简单,但是程序走了很多弯路。
想了很多办法,甚至把循环里的if拿掉了,将temp存入ArrayList然后sort输出最大也试了。事实就是,四重循环不拿掉,就是超时。

怎么办呢?上网查!
各种都说自己是正确答案的,代码天马行空魔鬼数字没几个看得懂的,甚至看得懂的几个还是错的,java写的没看到合适的好理解的算法后,看到了一篇c++的,思路很好,设值缓存。每次求矩形时,减去第一列加上下一列,不用每次都遍历循环,去掉了一层循环。很轻松的就编译通过了。代码如下
  1. import java.util.Scanner;
    
    public class Main1002 {
    
        static int a,b;
        static int[][] juxing = new int[1000][1000];
        static int[] tmp = new int[1000];
    
        public static int jisuanv(int v, int h) {
            int num = 0;
            if (h > 0) {
                num = tmp[v] - juxing[h-1][v] + juxing[a+h-1][v];
                return num;
            }
            for (int i = h; i < a+h; i++) {
                num = num + juxing[i][v];
            }
            return num;
        }
    
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int L = sc.nextInt();
            int W = sc.nextInt();
            int max = 0;
            int body;
            //将矩形各值赋值到数组
            for (int i = 0; i < L; i++) {
                for (int j = 0; j < W; j++) {
                    juxing[i][j] = sc.nextInt();
                }
            }
    
            a = sc.nextInt();
            b = sc.nextInt();
    
            //圈地时。对于行,有L-a种情况
            for (int i = 0; i <= L-a; i++) {
                body = 0;
                //m列计算出每列的值赋给tmp[m],并求矩形总值body(先求第一个矩形)
                for (int m = 0; m < b; m++) {
                    tmp[m] = jisuanv(m, i);
                    body = body + tmp[m];
                }
    
                if (body > max) {
                    max = body;
                }
               //0-b,b-W构成了所有的列
                //j列计算出每列的值赋给tmp[m],并求矩形总值body(后续矩形通过减去第一列加后一列算出)
                for (int j = b; j < W; j++) {
                    tmp[j] = jisuanv(j, i);
                    body = body +tmp[j] - tmp[j-b];
    
                    if (body > max) {
                        max = body;
                    }
                }
            }
            System.out.println(max);
        }
    }
参考博客(c++算法):http://blog.youkuaiyun.com/lmw21848/article/details/51072918


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值