分割矩阵---二分法

来源:互联网 发布:设计师必备软件 编辑:程序博客网 时间:2024/05/19 23:26

将一个N*M矩阵分成16份,找到所有划分中最小值的最大值
输入描述:
每个测试用例的第一行包含两个整数 n 和 m(1 <= n, m <= 75)
接下来的 n 行,每行包含 m 个 0-9 之间的数字,表示每块位置的价值。
输出描述:
划分中最小值的最大值
输入例子:
4 4
3332
3233
3332
2323
输出例子:
2

public class Main {    public static void main(String[] args) {        Scanner sc=new Scanner(System.in);        int n=sc.nextInt();        int m=sc.nextInt();        int a[][]=new int[n][m];        sc.nextLine();        for(int i=0;i<n;i++){            String str=sc.nextLine();            for(int j=0;j<m;j++){                a[i][j]=str.charAt(j)-'0';            }        }        sc.close();        int sum[][]=new int[n+1][m+1];//表示到i、j的所有数的和        for (int i=1; i<=n; i++){            for (int j = 1;j<=m; j++){                sum[i][j] = a[i-1][j-1] + sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1];//sum[i-1][j-1]为重叠部分            }        }        int low = 0;        int high = sum[n][m];        int res = 0;        while (low <= high){//二分法            int mid = low + (high - low) / 2;            if (GetMinValue(n, m, mid,sum)){//划分后mid是最小值,随着mid增大,答案也越大,能确保得到最大值                low = mid + 1;                res = mid;            }else {//mid不是最小,mid要再减小                high = mid - 1;            }        }        System.out.println(res);    }      public static boolean GetMinValue(int n, int m, int min,int sum[][]){        for (int i = 1; i < m - 2; i++){//竖切第一刀            for (int j = i + 1; j < m - 1; j++){//竖切第二刀                for (int k = j + 1; k < m; k++) {//竖切第三刀                    int cnt = 0;                    int pre = 0;                    for (int row = 1; row <= n; row++){//横切                        int s1 = getArea(pre,row, 0, i,sum);//1列                        int s2 = getArea(pre,row, i, j,sum);//2列                        int s3 = getArea(pre,row, j, k,sum);//3列                        int s4 = getArea(pre,row, k, m,sum);//4列                        if (s1 >= min && s2 >= min && s3 >= min && s4>= min){//若切出来的四块都比min大,min符合条件                            cnt++;                            pre = row;                        }                        if (cnt >= 4){//存在划分最小值比min大                                return true;                        }                    }                }            }        }        return false;    }      public static int getArea(int x1, int x2,int y1, int y2,int sum[][]){//(x1,y1)~(x2,y2)的面积和        return sum[x2][y2] + sum[x1][y1] - sum[x1][y2] - sum[x2][y1];    }}
原创粉丝点击