乐高铺砖——分治算法实现

乐高铺砖——分治算法实现_第1张图片

分析

用如上图所示的乐高砖铺一个边长为 2 n 2^n 2n的正方形地面。其中有一块是已经铺好的。先证明 ( 2 n ) 2 − 1 (2^n)^2-1 (2n)21能够被 3 3 3整除。
(1).当 n = 1 n=1 n=1时,显然 3 / 3 = 1 3/3=1 3/3=1,能够整除
(2).假设当 n = k n=k n=k时, 4 k − 1 = 3 ∗ A 4^k-1=3*A 4k1=3A成立
(3).则当 n = k + 1 n = k+1 n=k+1时, 4 k + 1 − 1 = 4 ( 4 k − 1 ) + 3 = 12 ∗ A + 3 4^{k+1}-1=4(4^k-1)+3=12*A+3 4k+11=4(4k1)+3=12A+3,此时也可被整除。即得证。(此时只是代表有可能被铺满,但是砖的形状未必如图)

分治思想

乐高铺砖——分治算法实现_第2张图片

  • 每次将地板平均分为四块,则可用递归解决此问题。但是由于分块后,有一个区域中有一块是已经铺上砖的。所以可将其他没有铺砖的区域紧靠分割原点的三块砖铺满。
  • 记左上角的第一个点为 s t a r t P o i n t ( 0 , 0 ) startPoint(0,0) startPoint(0,0),地板边长为 l l l,则中心四个点坐标为:
    左上角中心点 = ( s t a r t P o i n t . x + l / 2 − 1 , s t a r t P o i n t . y + l / 2 − 1 ) (startPoint.x+l/2-1,startPoint.y+l/2-1) (startPoint.x+l/21,startPoint.y+l/21)
    左下角中心点 = ( s t a r t P o i n t . x + l / 2 , s t a r t P o i n t . y + l / 2 − 1 ) (startPoint.x+l/2,startPoint.y+l/2-1) (startPoint.x+l/2,startPoint.y+l/21)
    右上角中心点 = ( s t a r t P o i n t . x + l / 2 − 1 , s t a r t P o i n t . y + l / 2 ) (startPoint.x+l/2-1,startPoint.y+l/2) (startPoint.x+l/21,startPoint.y+l/2)
    右下角中心点 = ( s t a r t P o i n t . x + l / 2 , s t a r t P o i n t . y + l / 2 ) (startPoint.x+l/2,startPoint.y+l/2) (startPoint.x+l/2,startPoint.y+l/2)
  • 同时可将分成的四块区域分别记为 ( 0 , 0 ) , ( 0 , 1 ) , ( 1 , 0 ) , ( 1 , 1 ) (0,0),(0,1),(1,0),(1,1) (0,0),(0,1),(1,0),(1,1):
  • 计算现有砖块所在区域:
 int coveredRegionX = (coveredPoint.x - startPoint.x) / halfLength;
 int coveredRegionY = (coveredPoint.y - startPoint.y) / halfLength;
public class Lego{
    
    private static int index = 1;//每铺上一块砖+1
    
    private static class Point{
       private int x;
       private int y;
       private int color_state;
       public Point(int x,int y){
           this.x = x;
           this.y = y;
           
       }
     
    }
    private static class Floor{
        public int len; //地板长度必须为2^n
        public int[][] floor ;
        public Floor(int len){
            this.len = len;
            floor = new int[len][len];
            for(int i = 0;i < len;i++){
                for(int j = 0;j < len;j++){
                    floor[i][j] = 0;
                }
            }
         }
        public Floor(int[][] floor){
            this.floor = floor;
            this.len = floor.length;
        }
        
    }
    /**
     * 覆盖一个区域
     * @param floor
     */
    public void coverPointInEachRegion(Point[][] needCovered,Floor floor){
       int color = index++;
        for(int i = 0;i < needCovered.length;i++){
            for(int j = 0; j < needCovered.length;j++){
                cover_current_point(floor,needCovered[i][j],color);
            }
        }
    }
   
    private void cover_current_point(Floor floor, Point point, int color) {
        if(floor.floor[point.x][point.y] == 0)
            floor.floor[point.x][point.y] = color;
    }

    /**
     * 计算需要覆盖的每个中心点的位置
     * 
     * @param startPoint
     * @param halfLength
     * @return
     */
    public  Point[][] cover(Point startPoint,int halfLength){
            Point[][] needCovered = new Point[2][2];
            needCovered[0][0] = new Point(startPoint.x+halfLength-1, startPoint.y+halfLength-1);
            needCovered[0][1] = new Point(startPoint.x+halfLength-1, startPoint.y+halfLength);
            needCovered[1][0] = new Point(startPoint.x+halfLength, startPoint.y+halfLength-1);
            needCovered[1][1] = new Point(startPoint.x+halfLength, startPoint.y+halfLength);

            return needCovered;
    }

    public void legoImpl(Floor floor,int length,Point startPoint,Point coveredPoint){
        
        if(length > 0){
           int  halfLength = length / 2;
            
            //计算现有砖块所在区域
            int coveredRegionX = (coveredPoint.x - startPoint.x) / halfLength;
            int coveredRegionY = (coveredPoint.y - startPoint.y) / halfLength;

            //铺砖
            Point[][] coveredPointList = cover(startPoint, halfLength);
            coveredPointList[coveredRegionX][coveredRegionY] = coveredPoint;
            
            //填充颜色
            coverPointInEachRegion(coveredPointList, floor);

            if(halfLength > 1){
                Point startPoint00 = startPoint;
                Point startPoint01 = new Point(startPoint.x, startPoint.y+halfLength);
                Point startPoint10 = new Point(startPoint.x+halfLength, startPoint.y);
                Point startPoint11 = new Point(startPoint.x+halfLength, startPoint.y+halfLength);
                
                legoImpl(floor,halfLength, startPoint00, coveredPointList[0][0]);
                legoImpl(floor,halfLength, startPoint01, coveredPointList[0][1]);
                legoImpl(floor,halfLength, startPoint10, coveredPointList[1][0]);
                legoImpl(floor,halfLength, startPoint11, coveredPointList[1][1]);
            }
     
            
        }
         
        
        

        
    }
    public static void main(String[] args) {
        Floor floor = new Floor(16);
      
        
        Lego lego = new Lego();
        Point startPoint = new Point(0, 0);
        Point coveredPoint = new Point(8,2);
        floor.floor[coveredPoint.x][coveredPoint.y] = -1;
        lego.legoImpl(floor, floor.len, startPoint, coveredPoint);

        for(int i = 0;i < floor.len;i++){
            for(int j = 0;j < floor.len;j++){
                System.out.print(floor.floor[i][j]+"\t");
            }
            System.out.println();
        }
        System.out.println("=========================================");
    }

}

你可能感兴趣的:(算法)