• PuyoPuyo DFS算法练习


    PuyoPuyo DFS算法练习

    题目和解析有空再整理。

    package puyopuyo;
    
    /**
     * @Author jinjun99
     * @Date Created in 2021/11/21 11:18
     * @Description
     * @Since version-1.0
     */
    public class Block {
    
        /**
         * 状态
         */
        int event = 0;
        /**
         * 方向
         */
        int dir = 0;
    
        /**
         * 列号
         */
        int col = 0;
        /**
         * 颜色
         */
        int[] val;
    
        public Block(int[] val) {
            this.val = val;
        }
    }
    
    
    package puyopuyo;
    
    /**
     * @Author jinjun99
     * @Date Created in 2021/11/21 13:00
     * @Description
     * @Since version-1.0
     */
    public class Point {
        int x = 0;
        int y = 0;
    
        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
    
        public Point() {
        }
    }
    
    
    package puyopuyo;
    
    import java.util.Arrays;
    import java.util.Stack;
    
    /**
     * @Author jinjun99
     * @Date Created in 2021/11/21 17:36
     * @Description
     * @Since version-1.0
     */
    public class Demo02 {
        /**
         * 宽度
         */
        private static int width = 4;
        /**
         * 高度
         */
        private static int height = 6;
        /**
         * 地图
         */
        private static int[][] map = new int[height][width];
        /**
         * 标记图
         */
        private static int[][] mark = new int[height][width];
        /**
         * 列的高度,y坐标
         */
        private static int[] tail = new int[width];
        private static int[] dirX = {1,0,-1,0};
        private static int[] dirY = {0,1,0,-1};
        /**
         * 当前块
         */
        private static Block block;
        /**
         * 地图初始化
         */
        private static void inti(int w){
            width = w;
            map = new int[height][width];
        }
        /**
         * 旋转一个角度
         * @param angle
         */
        private static void rotate(int angle){
            block.dir=(block.dir+angle)%4;
            //右边界
            if (block.dir==0&&block.col==width-1){
                block.col=width-2;
            }
            if (block.dir==2&&block.col==0){
                block.col=1;
            }
        }
        /**
         * 移动一段距离
         * @param distance
         */
        private static void move(int distance){
            block.col+=distance;
            //中间区域不用考虑
            if (block.col>=1 && block.col<=width-2){
                return;
            }
            //右方向看右边界
            if (block.dir==0 && block.col>=width-1){
                block.col=width-2;
                return;
            }
            //左方向看左边界
            if (block.dir==2 && block.col<=0){
                block.col=1;
                return;
            }
            //其他方向右越界(dis过大)
            if (block.col > width-1){
                block.col = width-1;
            }
            //其他方向左越界(dis过大)
            if (block.col < 0){
                block.col = 0;
            }
        }
        private static void hinder(int count,int life){
           // block.event = 2;
            int h = height-1;
            for (int i = 0; i < count; i++) {
                map[h-tail[i]][i] = -1*life;
                tail[i]++;
            }
        }
        /**
         * 更新当前块下落后的地图,记录列高度
         * @return
         */
        private static int land(){
            //1.将一个圆叠在另一个圆上,不留空隙。
            Point p1 = new Point();
            Point p2 = new Point();
            int h = height-1;
            if (block.event==0){
                switch (block.dir){
                    case 0:
                    {
                        p1.x = block.col;
                        p1.y = h-tail[block.col];
                        map[p1.y][p1.x] = block.val[0];
                        p2.x = block.col+1;
                        p2.y = h-tail[block.col];
                        map[p2.y][p2.x] = block.val[1];
                        tail[block.col]++;
                        tail[block.col+1]++;
                        break;
                    }
                    case 1:
                    {
                        p1.x = block.col;
                        p1.y = h-(tail[block.col]+1);
                        map[p1.y][p1.x] = block.val[0];
                        p2.x = block.col;
                        p2.y = h-tail[block.col];
                        map[p2.y][p2.x] = block.val[1];
                        tail[block.col]+=2;
                        break;
                    }
                    case 2:
                    {
                        p1.x = block.col;
                        p1.y = h-tail[block.col];
                        map[p1.y][p1.x] = block.val[0];
                        p2.x = block.col-1;
                        p2.y = h-tail[block.col-1];
                        map[p2.y][p2.x] = block.val[1];
                        tail[block.col]++;
                        tail[block.col-1]++;
                        break;
                    }
                    case 3:
                    {
                        p1.x = block.col;
                        p1.y = h-tail[block.col];
                        map[p1.y][p1.x] = block.val[0];
                        p2.x = block.col;
                        p2.y = h-(tail[block.col]+1);
                        map[p2.y][p2.x] = block.val[1];
                        tail[block.col]+=2;
                        break;
                    }
                    default:
                        break;
                }
                solution(p1,p2);
            }
            int j=0;
            for (int i = 0; i < width; i++) {
                j= Math.max(tail[i], j);
            }
            return j;
        }
        private static Point[] drop = new Point[width*height];
    
        /**
         * 块下落后的消除
         * @param p1
         * @param p2
         */
        private static void solution(Point p1,Point p2){
            int dropNum = 2;
            drop[0] = p1;
            drop[1] = p2;
    
            while (dropNum!=0){
                for (int i = 0; i < dropNum; i++) {
                    //一组两个颜色相同
                    if (mark[drop[i].y][drop[i].x] == 1){
                        continue;
                    }
                    dfs(drop[i].x,drop[i].y);
                    clear();
                }
                markHinder();
                dropNum = updateMap();
            }
        }
        private static Stack<Point> elimP = new Stack<>();
        private static int[][] mark2 = new int[height][width];
    
        /**
         * 搜索4个同色相连块,放入搜索队列
         * @param x
         * @param y
         */
        private static void dfs(int x,int y){
            mark2[y][x] = 1;
            elimP.push(new Point(x,y));
            for (int i = 0; i < 4; i++) {
                int a = x+dirX[i];
                int b = y+dirY[i];
                if (a>=0&&a<width&&b>=0&&b<height&&map[b][a]==map[y][x]&&mark2[b][a]==0){
                    dfs(a,b);
                }
            }
        }
    
        /**
         * 根据搜索结果清理同色块
         */
        private static void clear(){
            int s = elimP.size();
            if (s>=4){
                for (int i = 0; i < s; i++) {
                    Point p = elimP.pop();
                    map[p.y][p.x]=0;
                    mark[p.y][p.x]=1;
                    tail[p.x]--;
                }
            }
            elimP.removeAllElements();
    
        }
        /**
         * 消除同色块后,更新阻碍块寿命和位置,顺便消除标记
         */
        private static void markHinder(){
            int h = height-1;
            for (int i = 0; i < width; i++) {
                for (int j = 0; j <= tail[i]; j++) {
                    if (map[h-j][i]<0){
                        if (check(h-j,i)==1){
                            map[h-j][i] += 1;
                            if (map[h-j][i]==0){
                                tail[i]--;
                            }
                        }
                    }
                }
            }
            mark2 = new int[height][width];
            mark = new int[height][width];
        }
    
        /**
         * 同色块消除后,把空中的块放下来,顺便放入搜索队列
         * @return 空中块的数量
         */
        private static int updateMap(){
            int c = 0;
            int s = 0;
            int sum = 0;
            int h = height-1;
            for (int i = 0; i < width; i++) {
                for (int j = 0; j < tail[i]; j++) {
                    int l = h-j;
                    if (map[l][i]==0){
                        if (j>=tail[i]){
                            break;
                        }
                        //j=1,c=3
                        while (map[l-c][i]==0&&j+c<tail[i]){
                            c++;
                        }
                        if (j+c+1==tail[i]){
                            tail[i]=j;
                            break;
                        }
                        if (map[l-c][i]>0) {
                            map[l][i] = map[l - c][i];
                            map[l - c][i] = 0;
                            drop[s].x = i;
                            drop[s++].y = l;
                            sum++;
                        }
                        if (map[l-c][i]<0) {
                            map[l][i] = map[l - c][i];
                            map[l - c][i] = 0;
                        }
                    }
                }
            }
            return sum;
    
        }
    
        /**
         * 查看阻碍块四周是否有爆裂的同色块
         * @param y
         * @param x
         * @return
         */
        private static int check(int y,int x){
            for (int i = 0; i < 4; i++) {
                int a = y+dirY[i];
                int b = x+dirX[i];
                if (a>=0&&b>=0&&a<height&&b<width&&mark[a][b]==1){
                    return 1;
                }
            }
            return 0;
        }
    
        public static void main(String[] args) {
            int sum = 0;
            block = new Block(new int[]{1,1});
            rotate(0);
            move(1);
            sum = land();
            hinder(2,2);
            hinder(4,1);
            block = new Block(new int[]{2,2});
            rotate(0);
            move(2);
            sum = land();
            block = new Block(new int[]{1,1});
            rotate(1);
            move(2);
            sum = land();
            block = new Block(new int[]{2,2});
            rotate(1);
            move(3);
            sum = land();
    
            for (int i = 0; i < height; i++) {
                for (int j = 0; j < width; j++) {
                    if (map[i][j]<0){
                        System.out.print(map[i][j]);
                    }else {
                        System.out.print(" "+map[i][j]);
                    }
                    if (j==width-1){
                        System.out.println();
                    }
                }
            }
            System.out.println("最高列长度是:"+sum);
        }
    }
    
    

    负数代表阻碍块生命值,正数代表颜色,0为空

    打印一下过程:

     0 0 0 0
     0 0 0 0
     0 0 0 0
     0 0 0 0
     0 0 0 0
     0 1 1 0
    最高列长度是:1
    
     0 0 0 0
     0 0 0 0
     0 0 0 0
     0-1 2 0
    -1-2-1 2
    -2 1 1-1
    最高列长度是:3
    
     0 0 0 0
     0 0 1 0
     0 0 1 0
     0-1 2 0
    -1-2-1 2
    -2 1 1-1
    最高列长度是:5
    
     0 0 0 0
     0 0 0 0
     0 0 0 0
     0 0 0 0
    -1 0 0 0
    -1-1 0 0
    最高列长度是:2
    
  • 相关阅读:
    NOIP201208同余方程
    NOIP模拟赛 最佳组合
    NOIP模拟赛 拓展
    CF1253E Antenna Coverage(DP)
    LOJ6033「雅礼集训 2017 Day2」棋盘游戏 (博弈论,二分图,匈牙利算法)
    CF582E Boolean Function(DP,状态压缩,FMT)
    CF750G New Year and Binary Tree Paths(DP)
    Codeforces Round 596 题解
    AGC008E Next or Nextnext(组合计数,神奇思路)
    ARC082E ConvexScore(神奇思路)
  • 原文地址:https://www.cnblogs.com/jinjun99/p/15597658.html
Copyright © 2020-2023  润新知