您的位置:首页 > 编程语言

【算法】网易2017校园招聘笔试程序题(分田地)

2016-08-04 11:17 801 查看

题目

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

输入描述

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

输出描述

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

结果

输入例子

4 4

3 3 3 2

3 2 3 3

3 3 3 2

2 3 2 3

输出例子

2

算法思路

咋一看这个题目不是傻逼嘛,只求矩阵最小值不就可以么。。。细思之后才发现自己傻逼。题目的意思是对于m*n的矩阵,横竖三刀,也就是十六份中,牛牛得最小值。但是因为有不同的切法,所以在所有分法中,牛牛要得到最小值中最大的那个,因为他朋友希望牛牛能拿的价值尽可能大。

那这个题目如何解呢?因为横竖切法太多了,都不知道如何下手,暴力破解也不是很好办啊。但是冷静之后想了下,其实思路我觉得也挺简单。

1)就是对于m*n的矩阵,首先找到最小值的那块,你想你希望牛牛拿的多,那这块肯定是要和它周边分在一起的,那对于最小这块可以和它分在一起的,无非就是向上合并,或者向下合并,或者向左合并,或者向右合并嘛,这样就得到一个行或者列少一行的新矩阵。

2)对于新矩阵再次找最小块,然后是向上合并,或者向下合并,或者向左合并,或者向右合并,完全就是上面的一个新轮回。

3)直到矩阵合并为4*4的矩阵,其中最小的就是牛牛获得最小值。

需要注意的是,每一次合并都不能确定一定是往某一个方向合并,所以必须每个方向都合并,这样每种情况下最后会产生不一样的4*4矩阵,也就是能得到若干最小值,而牛牛最终得到的价值就是这些最小值中最大的。

算法实现

public class Main{
public static int minVal;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt()-1;//N行
int m = sc.nextInt()-1;//M列
int matrix[][] = new int[n+1][m+1];
int minpos[]=new int[2];//记录矩阵中最小值的位置
for(int i=0;i<=m;i++){
for(int j=0;j<=n;j++){
matrix[i][j]=sc.nextInt();
}
}

getMinpos(matrix,m,n,minpos);//获取矩阵中最小值位置
minVal=matrix[minpos[0]][minpos[1]];//初始化牛牛获得的最小价值
System.out.println("所有分法:");
getMaxVal(matrix,m,n,minpos);//分田过程
System.out.println("最终牛牛获得的价值:"+minVal);//输出牛牛获得的价值
}

private static void getMaxVal(int[][] matrix, int m, int n, int[] minpos) {
int oldMatrix[][] = new int[m+1][n+1];
oldMatrix=matrix;//保存原矩阵,回溯返回到这时还需要用原来的矩阵而不是被子过程改变的矩阵
int m0 = minpos[0];
int n0 = minpos[1];
//最后得到4*4返回
if(m==n&&m==3){
for(int i=0;i<=3;i++){
System.out.println(java.util.Arrays.toString(matrix[i]));
}
System.out.println();
return;
}
//向上合并
if(m0>0&&m>3){
matrix=mergeMatrix(matrix,m,n,m0-1,n,minpos,1);
getMaxVal(matrix,matrix.length-1,matrix[0].length-1,minpos);
}
matrix=oldMatrix;
//向下合并
if(m0<m&&m>3){
matrix=mergeMatrix(matrix,m,n,m0,n,minpos,1);
getMaxVal(matrix,matrix.length-1,matrix[0].length-1,minpos);
}
matrix=oldMatrix;
//向左合并
if(n0>0&&n>3){
matrix=mergeMatrix(matrix,m,n,m,n0-1,minpos,-1);
getMaxVal(matrix,matrix.length-1,matrix[0].length-1,minpos);
}
matrix=oldMatrix;
//向右合并
if(n0<n&&n>3){
matrix=mergeMatrix(matrix,m,n,m,n0,minpos,-1);
getMaxVal(matrix,matrix.length-1,matrix[0].length-1,minpos);
}
}

private static int[][] mergeMatrix(int[][] matrix, int m, int n,int mergem,int mergen, int[] minpos,int flag) {
int[][] temp=null;
if(flag==1){//向上合并 或 向下合并
temp = new int[m][n+1];
for(int i=0;i<=m;i++){
for(int j=0;j<=n;j++){
if(i<mergem){
temp[i][j] = matrix[i][j];
}
else if(i==mergem){
temp[i][j] = matrix[i][j]+matrix[i+1][j];
}else{
temp[i-1][j] = matrix[i][j];
}
}
if(i==mergem){
i++;
}
}
}else if(flag==-1){//向左合并 或 向右合并
temp = new int[m+1]
;
for(int i=0;i<=m;i++){
for(int j=0;j<=n;j++){
if(j<mergen){
temp[i][j]=matrix[i][j];
}
else if(j==mergen){
temp[i][j]=matrix[i][j]+matrix[i][j+1];
j++;
}else{
temp[i][j-1]=matrix[i][j];
}
}
}
}
//合并后的矩阵求其中最小的位置
getMinpos(temp,temp.length-1,temp[0].length-1,minpos);
return temp;
}

//获取矩阵最小值位置
private static void getMinpos(int[][] matrix,int m,int n,int[] minpos) {
int min = Integer.MAX_VALUE;
for(int i=0;i<=m;i++){
for(int j=0;j<=n;j++){
if(matrix[i][j]<min){
min=matrix[i][j];
minpos[0]=i;
minpos[1]=j;
}
}
}
if(minVal<min){
minVal=min;
}
}

}


示例

注意我的输入矩阵是带空格的,原题是不带空格,所以还需要以字符串输入再切分。

5 5
3 3 3 2 2
3 2 2 3 3
3 3 3 3 2
1 1 1 1 1
2 2 2 2 2
所有分法:
[3, 3, 5, 2]
[3, 2, 5, 3]
[4, 4, 8, 3]
[2, 2, 4, 2]

[3, 3, 3, 4]
[3, 2, 2, 6]
[4, 4, 4, 7]
[2, 2, 2, 4]

[3, 3, 5, 2]
[3, 2, 5, 3]
[3, 3, 6, 2]
[3, 3, 6, 3]

[3, 3, 3, 4]
[3, 2, 2, 6]
[3, 3, 3, 5]
[3, 3, 3, 6]

[6, 3, 2, 2]
[5, 2, 3, 3]
[8, 4, 4, 3]
[4, 2, 2, 2]

[6, 3, 2, 2]
[5, 2, 3, 3]
[6, 3, 3, 2]
[6, 3, 3, 3]

最终牛牛获得的价值:2


结语

因为牛客网还没出真题oj所以无法知道是否通过,如果有人发现算法有误,欢迎拍砖!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息