zoukankan      html  css  js  c++  java
  • 1728. 猫和老鼠 II 记忆化搜索 暴力

    1728. 猫和老鼠 II 记忆化搜索 暴力

    题目大意:

    中文题目就自己看吧,但是要注意一下这个题目的数据范围:

    • (rows == grid.length)
    • (cols = grid[i].length)
    • (1 <= rows, cols <= 8)
    • (grid[i][j]) 只包含字符 ('C')('M')('F')('.')('#')
    • (grid) 中只包含一个 $'C' (,)'M'$ 和 $'F' $。
    • (1 <= catJump, mouseJump <= 8)

    题解:

    这种带有博弈性质的题目,如果范围小可以直接暴力搜索,然后可以加一点优化就是记忆化搜索。

    定义(dp[x1][y1][x2][y2][step][now]) 表示当前老鼠在位置 ((x1,y1)) ,猫在位置 ((x2,y2)) ,已经走了 (step) 步了,当前的先手是 老鼠now = 0,猫 now = 1。

    对于先手来说只要子状态有一个是返回false,那么表示先手必胜。

    然后如果使用题目的中1000步来做限制,那么会TLE,然后经过测试发现并不需要这么大,200也是可以过的。

    这个题目用到了必胜和必败状态的推导。

    必胜必败状态的推导

    class Solution {
    public:
    int dp[10][10][10][10][200][2];
    vector<string> Grid;
    int dx[4]={0,1,0,-1};
    int dy[4]={1,0,-1,0};
    int clen,mlen,rows,cols;
        bool dfs(int sx,int sy,int gx,int gy,int step,int cur){
            int &ans = dp[sx][sy][gx][gy][step][cur];
            if(ans!=-1) return ans;
            if(step>=199) return ans = cur;
            if(cur==0){
                if(!dfs(sx,sy,gx,gy,step+1,1)) return true;
                for(int i=0;i<4;i++){
                    for(int j=1;j<=mlen;j++){
                        int tx = sx + dx[i]*j;
                        int ty = sy + dy[i]*j;
                        if(tx<0||ty<0||tx>=rows||ty>=cols) break;
                        if(Grid[tx][ty]=='#') break;
                        if(Grid[tx][ty]=='F') return ans = true;
                        if(tx==gx&&ty==gy) continue;
                        if(!dfs(tx,ty,gx,gy,step+1,1)) return ans = true;
                    }
                }
                return ans = false;
            }
            else{
                if(!dfs(sx,sy,gx,gy,step+1,0)) return true;
                for(int i=0;i<4;i++){
                    for(int j=1;j<=clen;j++){
                    int tx = gx + dx[i]*j;
                    int ty = gy + dy[i]*j;
                    if(tx<0||ty<0||tx>=rows||ty>=cols) break;
                        if(Grid[tx][ty]=='#') break;
                        if(Grid[tx][ty]=='F') return ans = true;
                        if(tx==sx&&ty==sy) return ans = true;
                        if(!dfs(sx,sy,tx,ty,step+1,0)) return ans = true;
                    }
                }
                return ans = false;
            }
        }
        bool canMouseWin(vector<string>& grid, int catJump, int mouseJump) {
            Grid = grid;
            clen = catJump,mlen = mouseJump;
            rows = grid.size(),cols = grid[0].length();
            int sx,sy,gx,gy;
            for(int i=0;i<rows;i++){
                for(int j=0;j<cols;j++){
                    if(grid[i][j]=='M') sx = i,sy = j;
                    if(grid[i][j]=='C') gx = i,gy = j;
                }
            }
            memset(dp,-1,sizeof(dp));
            bool flag = dfs(sx,sy,gx,gy,0,0);
            bool ans;
            if(flag) ans = true;
            else ans = false;
            return ans;
        }
    };
    
  • 相关阅读:
    数组
    循环(二)
    循环——笔记
    C#基础(四)
    C#基础(三)
    安卓帮助文档
    增加线程异步发送消息的方法二(Runnable)
    增加线程异步发送消息的方法一(Thread)
    获取下拉框的值
    获取表中字段最大值,并且保存在前台页面中
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/14321888.html
Copyright © 2011-2022 走看看