[编程题] 分田地

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

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



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

 

输入例子:
4 4
3332
3233
3332
2323

 

输出例子:
2

import java.util.*;
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 [][] arr=new int[n][m];
for(int i=0;i<n;i++){
String s=sc.next();
for(int j=0;j<m;j++){
arr[i][j]=Integer.parseInt(s.substring(j,j+1));
}
}
System.out.println(getMax(arr,n,m));
}
sc.close();
}

public static int getMax(int [][] arr,int n,int m){
int res=0;
int [][] dp=new int[n+1][m+1];//dp[i][j]:从(0,0)到(i-1,j-1)的所有数的和
for(int i=1;i<n+1;i++){
for(int j=1;j<m+1;j++){
dp[i][j]=dp[i-1][j]+dp[i][j-1]+arr[i-1][j-1]-dp[i-1][j-1];
}
}
int l=0;
int r=dp[n][m];
while(l<=r){
int mid=(l+r)/2;
if(check(dp,mid)){
l=mid+1;
res=mid;
}else{
r=mid-1;
}
}
return res;
}

public static boolean check(int [][] dp,int key){
int n=dp.length;
int m=dp[0].length;
for(int i=1;i<n-3;i++){
for(int j=i+1;j<n-2;j++){
for(int k=j+1;k<n-1;k++){//注意数组的界限,横着最后一刀,后面必须至少留一个元素
int cnt=0;int last=0;
for(int l=1;l<m;l++){//同理,纵着切时,最后面也要留一个元素,因此不能取到m
int s1=calc(dp,0,last,i,l);
int s2=calc(dp,i,last,j,l);
int s3=calc(dp,j,last,k,l);
int s4=calc(dp,k,last,n-1,l);//同理不能取到n
if(s1>=key&&s2>=key&&s3>=key&&s4>=key){
last=l;
cnt++;
}
}
if(cnt>=4){
return true;
}
}
}
}
return false;
}
public static int calc(int[][] dp,int preX,int preY,int nowX,int nowY){
return dp[nowX][nowY]-dp[preX][nowY]-dp[nowX][preY]+dp[preX][preY];
}
}

posted @ 2016-08-16 22:21  kimi9py  阅读(750)  评论(0编辑  收藏  举报