# 算法-数组:找出符合某条件的最大矩形区域

import java.lang.String;

class Point {

private int x = 0;
private int y = 0;        //点的(X,y)坐标;数组表示为:arr[y][x]

Point() {}
Point(int pX, int pY){ setPoint(pX, pY); }
Point(Point point){ setPoint(point); }
public int getX(){ return x; }
public int getY(){ return y; }
public void setPoint(int pX, int pY) {
x = pX;
y = pY;
}
public void setPoint(Point point) {
x = point.getX();
y = point.getY();
}

public Point right(){ return new Point((x+1),y); }
public void right(int n){ x = x + n; }
public Point down(){ return new Point(x,(y+1)); }
public void down(int n){ y = y + n; }
public Point rightdown(){ return new Point( (x+1), (y+1) ); }
public Point newPointBy(int X,int Y){ return new  Point( (x+X), (y+Y) ); }
public Point newPointBy(Point point){ return newPointBy( point.getX(), point.getY() ); }
}

class Rect {

private Point pStart;        //矩形的左上坐标
private Point pEnd;                //矩形的右下坐标

Rect() {
pStart = new Point();
pEnd   = new Point();
}
Rect(int pX, int pY) {
pStart = new Point(pX,pY);
pEnd   = new Point(pX,pY);
}
Rect(int pSX, int pSY,int pEX, int pEY) {
pStart = new Point(pSX,pSY);
pEnd   = new Point(pEX,pEY);
}
Rect(Point pS, Point pE) {
pStart = new Point(pS);
pEnd   = new Point(pE);
}

public Point getStartPoint(){ return pStart; }
public Point getEndPoint(){ return pEnd; }
public void setRectStart(Point point){ pStart.setPoint(point); }
public void setRectStart(int pX,int pY){ pStart.setPoint(pX,pY); }
public void setRectEnd(Point point){ pEnd.setPoint(point); }
public void setRectEnd(int pX,int pY){ pEnd.setPoint(pX,pY); }
public void setRect(Point pS, Point pE){
pStart.setPoint(pS);
pEnd.setPoint(pE);
}

public int getAcre() {
return 0;
}
public int getRound() {
return 0;
}

}

class Method {

private int[][] ary;
private int X,Y;

//绑定Method的操作数组;
public boolean arrBind(int[][] arrData) {
if(arrData.length>=2) {
if(arrData[1].length>=2) {
ary = arrData;
return true;
}
}
showFaildString();
ary = null;
return false;
}
public boolean arrBind(int x, int y) {

if( (x>20)||(y>20) ) {
showFaildString();
return false;
}
ary = new int[y][x];
for(int i=0; i<y; i++) {
for(int j=0; j<x; j++) {
ary[i][j] = random_01();
}
}
return true;
}
public void arrDisConnect() {
ary = null;
}

public Rect maxArea() {

if(!checkBind()) return null;
boolean bFound = false;
Point pStart = new Point();
Point pEnd;
Rect rRetVal = new Rect();

for(int i=0; i<ary.length; i++) {
for(int j=0; j<ary[i].length; j++) {
//如果该点值为'0',生成最大矩形;
if(ary[i][j]==0) {
pStart.setPoint(j,i);
pEnd = getMaxEndPoint(pStart);
if(pEnd!=null) {
rRetVal.setRect( pStart, pEnd );
bFound = true;
}
}
}
}
if(bFound)
return rRetVal;
else
return null;
}
public void drawArea(Rect area) {
if(!checkBind()) return;
System.out.println("Start---------------------------------------------");
for(int i=0; i<ary.length; i++) {
System.out.print("  ");
for(int j=0; j<ary[i].length; j++){
if( (area.getStartPoint().getX()<=j)&&(j<=area.getEndPoint().getX())&&(area.getStartPoint().getY()<=i)&&(i<=area.getEndPoint().getY()) )
System.out.print(" *");
else
System.out.print(" "+ary[i][j]);
}
System.out.println("");
}
}
public void drawArea() {
if(!checkBind()) return;
System.out.println("Start---------------------------------------------");
for(int i=0; i<ary.length; i++) {
System.out.print("  ");
for(int j=0; j<ary[i].length; j++){
System.out.print(" "+ary[i][j]);
}
System.out.println("");
}
}
public int getLastMaxAreaSize() {
if(!checkBind()) return -1;
return X*Y;
}
//形式成最大矩形 返回第1最大矩形面积终点坐标
private Point getMaxEndPoint(Point pStart) {
boolean bFound = false;
if(!checkBind()) return null;
if(!isValidStart(pStart)) return null;
if(!isZero(pStart.right())) return null;
if(!isZero(pStart.down())) return null;
if(!isZero(pStart.rightdown())) return null;

int x=0,y;
do {
x++;
y=1;
while((ary.length>(pStart.getY()+y+1))&&appendH(pStart,x,y)) {
y++;
}

if( (x+1)*(y+1)>(X+1)*(Y+1) ) {
X = x;
Y = y;
bFound = true;
}
}while((ary[pStart.getY()].length>(pStart.getX()+x+1))&&appendW(pStart,x,1));

if(bFound)
return pStart.newPointBy(X,Y);
else
return null;
}
//横向(右)追加矩形面积 成功返回true
private boolean appendW(Point pThis, int X, int Y) {
int xVal = pThis.getX()+X+1;
for(int i=0; i<=Y; i++) {
if(ary[pThis.getY()+i][xVal]==1)
return false;
}
return true;
}
//纵向(下)追加矩形面积 成功返回true
private boolean appendH(Point pThis, int X, int Y) {
int yVal = pThis.getY()+Y+1;
for(int i=0; i<=X; i++) {
if(ary[yVal][pThis.getX()+i]==1)
return false;
}
return true;
}
private boolean isZero(int pX,int pY){ return (ary[pY][pX]==0)?true:false; }
private boolean isZero(Point pStart){ return isZero(pStart.getX(),pStart.getY()); }
private boolean isValidStart(int pX, int pY){ return isZero(pX,pY)?( (ary.length<=(pY+1))||(ary[pY].length<=(pX+1))?false:true ):false; }
private boolean isValidStart(Point pStart){ return isValidStart(pStart.getX(),pStart.getY()); }
private boolean checkBind() {
if(ary==null) {
showFaildString();
return false;
}

return true;
}
private int random_01(){
//return 1;
return (Math.random()*10>7)?1:0;
}
private void showFaildString() {
System.out.println("Method.ary is null;");
}
}

public class JavaApp {

public static void main(String[] args) {

int arr[][] = {
{1, 1, 1, 1, 0, 0, 1},
{1, 0, 0, 1, 0, 0, 1},
{0, 0, 0, 0, 0, 0, 0},
{1, 0, 1, 0, 1, 0, 1},
{1, 0, 1, 0, 0, 1, 1},
{1, 0, 0, 0, 0, 1, 1},
{1, 0, 0, 0, 0, 1, 0},
};

Rect myRect;
Method meth = new Method();
Point pStart, pEnd, pTemp;

switch(args.length) {
case 1:
if(!meth.arrBind(Integer.parseInt(args[0]),Integer.parseInt(args[0]))) System.exit(0);
break;
case 2:
if(!meth.arrBind(Integer.parseInt(args[0]),Integer.parseInt(args[1]))) System.exit(0);
break;
default:
if(!meth.arrBind(arr)) System.exit(0);
break;
}

meth.drawArea();

myRect = meth.maxArea();
if(myRect==null) {