博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
网易——分田地,竖切枚举+二分查找
阅读量:6854 次
发布时间:2019-06-26

本文共 2321 字,大约阅读时间需要 7 分钟。

  hot3.png

题目描述

牛牛和 15 个朋友来玩打土豪分田地的游戏,牛牛决定让你来分田地,地主的田地可以看成是一个矩形,每个位置有一个价值。分割田地的方法是横竖各切三刀,分成 16 份,作为领导干部,牛牛总是会选择其中总价值最小的一份田地, 作为牛牛最好的朋友,你希望牛牛取得的田地的价值和尽可能大,你知道这个值最大可以是多少吗?

输入描述:

每个输入包含 1 个测试用例。每个测试用例的第一行包含两个整数 n 和 m(1 <= n, m <= 75),表示田地的大小,接下来的 n 行,每行包含 m 个 0-9 之间的数字,表示每块位置的价值。

输出描述:

输出一行表示牛牛所能取得的最大的价值。

示例1

输入

4 43332323333322323

输出

2

【解决】

① 一样难懂的题意。。。。

1. 要是穷举的话,竖切三刀和横切三刀都得枚举,然后组合在一块是一种方案,随着数据的增大,时间会越来越长O(N^6)。

2. 只枚举竖切的三刀,然后采用二分值寻找横切方案,相当于把横切的穷举O(N^3)变成了O(log(N)),从而在整体上降低了时间复杂度。

3. 二分值方法是利用我们寻找的这个值肯定是在0和所有田地价值总和sum之间,所以使用二分查找,一点点缩小范围。

4. 寻找横切方案时,先假设当前行就是被横切的那一行,那么它新形成的四块地,每块地的价值都得大于等于这个二分值,如果满足条件,就继续寻找下一个横切线,如果最后可以分成比二分值大的16块地(甚至更多,说明二分值偏小),说明该二分值就是我们要找的值(或者此二分值偏小,我们继续调整二分范围);否则当前分割方案不行,继续枚举下个方案,调整二分范围。

输入示例
4 4 
3332 
3233 
3332 
2323 
输出 
sum矩阵为
3 6 9 11 
6 11 17 22  
9 17 26 33 
11 22 33 43 
mid依次为
21->10->4->1->2

import java.util.Scanner;

/**

 * 网易——分田地,竖切枚举+二分查找,又是一个。。。题
 * created by liyurong
 **/
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()){
            int n = sc.nextInt();
            int m = sc.nextInt();
            int[][] fields = new int[n][m];
            for (int i = 0;i < n;i ++){
                char[] tmp = sc.next().toCharArray();
                for (int j = 0;j < m;j ++){
                    fields[i][j] = tmp[j] - '0';
                }
            }

            int[][] sum = new int[n + 1][m + 1];

            for (int i = 1;i <= n;i ++){
                for (int j = 1;j <= m;j ++){
                    sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + fields[i - 1][j - 1];
                }
            }

            int left = 0;

            int right = sum[n][m];
            int res = 0;
            while (left <= right){
                int mid = (right - left) / 2 + left;
                if (judge(mid,n,m,sum)){
                    left = mid + 1;
                    res = mid;
                }else {
                    right = mid - 1;
                }
            }
            System.out.println(res);
        }
        sc.close();
    }
    public static boolean judge(int x,int n,int m,int[][] sum){
        for (int i = 1;i <= m - 3;i ++){
            for (int j = i + 1;j <= m - 2;j ++){
                for (int k = j + 1;k <= m - 1;k ++){
                    int lastRow = 0;
                    int count = 0;
                    for (int row = 1;row <= n;row ++){
                        int sum1 = cal(row,i,lastRow,0,sum);
                        int sum2 = cal(row,j,lastRow,i,sum);
                        int sum3 = cal(row,k,lastRow,j,sum);
                        int sum4 = cal(row,m,lastRow,k,sum);
                        if (sum1 >= x && sum2 >= x && sum3 >= x && sum4 >= x){
                            lastRow = row;
                            count ++;
                        }
                    }
                    if (count >= 4){
                        return true;
                    }
                }
            }
        }
        return false;
    }
    public static int cal(int x,int y,int i,int j,int[][] sum){
        return sum[x][y] - sum[i][y] - sum[x][j] + sum[i][j];
    }
}

 

转载于:https://my.oschina.net/liyurong/blog/1826010

你可能感兴趣的文章
ruby 集合
查看>>
harbor进程组件化运行及systemd 进程日志分写
查看>>
Web自动化测试中使用groovy实现页面的对象化
查看>>
RHEL5基于RSA的公匙和私匙加密认证SSH应用于服务器远程备份
查看>>
让你成功安装vscode中go的相关插件
查看>>
Java仿雷电及其源代码
查看>>
linux关机命令
查看>>
Visual studio Express 2012 for Web 试用
查看>>
ruby初级语法知识
查看>>
CA证书服务器(1) 数据加密技术
查看>>
Qt学习之路(23): 自定义事件
查看>>
如何让Windows 2003更加安全
查看>>
烂泥:使用Navicat for SQL Server新建数据库、用户及权限赋予
查看>>
采用hadoop对日志进行分布式分析框架
查看>>
服务器监控和虚拟机管理之六PRO的配置与实现
查看>>
【转】烂泥:查看MySql版本号命令
查看>>
MFC绘制直方图和饼图
查看>>
tf.minimize
查看>>
自己动手编写 IronPython IDE
查看>>
Eclipse:Eclipse平台技术概述
查看>>