DFS

作者: 魔芋辣椒 | 来源:发表于2020-08-06 09:56 被阅读0次

    一、 背包,资源分配等求一维线性最值或全排列问题

    void dfs(int x,int sum){
        if(x>n)return;  //当前数量超过背包容量,资源总数,或数字总数,return
        else{       
            if(sum>maxP)maxP=sum;
            for(int i=0;i<8;i++)//遍历一维数组
                if(vis[i]==0){//遍历没有被访问过的节点
                    vis[i]=1;
                    dfs(x+w[i],sum+pian[i]);
                    vis[i]=0;//回溯
                }
        }
    }
    

    另一种写法

    void dfs2(int index,int sumC,int sumW){
        if(index==8){
    
            return;
        }
            dfs2(index+1,sumC,sumW);//跳过index
        if(sumW <= n) {
            if (  sumC > maxP)
                maxP = sumC;
            dfs2(index + 1, sumC + pian[index], sumW + w[index]);//包含index
        }
    }
    

    二、地图问题

    回溯标记是否需要还原

    ​ 如果问题是求,所有可能的情况,如所有的可能路径,所有的排列,则需要需要还原。此时 123和132被认为是两条路

    ​ 如果问题是求面积,求最佳路径,则不需要

    添加dir数组,进行移动

    岛屿的最大面积

    void dfs(int ax,int ay,vector<vector<int>>& grid){
            w++;
            for(int k=0;k<4;k++){
                int x=ax+dir[k][0];
                int y=ay+dir[k][1];
                if(checkV(x,y,grid)){
                    visited[x][y]=1;
                    dfs(x,y,grid);
                }
            }
        }
    

    第二种递归解法

     int maxAreaOfIsland(int grid[][]) {
            int max = 0; // 记录最大岛屿面积
           
            for (int i = 0; i < grid.length; i++) {
                for (int j = 0; j < grid[0].length; j++) {
                    if (grid[i][j] == 1) { // 
                        int count = DFS(grid, visited, i, j, 0);
                        max = max > count ? max : count;
                    }
                }
            }
            return max;
        }
    
      int DFS(int grid[][],bool visited[][],int x,int y,int count) {
            if (!valid(grid, visited, x, y)) {
                return count;
            }
            visited[x][y] = true;
            for (int i = 0; i < 4; i++) { // 上下左右进行遍历
                count = DFS(grid, visited, x + move[i][0], y + move[i][1], count);
            }
            return count+1; // 更新岛屿面积
        }
    
    
    

    解数独

    编写一个程序,通过已填充的空格来解决数独问题。

    一个数独的解法需遵循如下规则:

    数字 1-9 在每一行只能出现一次。
    数字 1-9 在每一列只能出现一次。
    数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
    空白格用 '.' 表示

    // row[x][u]表示第x行是否已经填过数字u(0-8)
        // col[y][u]表示第y行是否已经填过数字u(0-8)
        // box[x / 3][y / 3][u]表示第[x/3,y/3]个box是否已经填过数字u(0-8)
    
        bool row[9][9] = {0}, col[9][9] = {0}, cell[3][3][9] = {0};
        void solveSudoku(vector<vector<char>>& board) {
            for (int i = 0; i < 9; i ++ ) {
                for (int j = 0; j < 9; j ++ ) {
                    char c = board[i][j];
                    if (c != '.') {
                        int u = c - '1'; // u: '1' - '1' = 0
                        row[i][u] = col[j][u] = cell[i / 3][j / 3][u] = true;
                    }
                }
            }
    
            dfs(board, 0, 0);
        }
    
        bool dfs(vector<vector<char>>& board, int x, int y) {
            if (y == 9) x ++ , y = 0; // 先改变
            if (x == 9) return true; // 填完所有格子,返回true
    
            if (board[x][y] != '.') return dfs(board, x, y + 1);
            
            for (int i = 0; i < 9; i ++ ) {
                if (!row[x][i] && !col[y][i] && !cell[x / 3][y / 3][i]) {
                    board[x][y] = i + '1';
                    row[x][i] = col[y][i] = cell[x / 3][y / 3][i] = true;
    
                    // 如果下面搜索后是对的,就提前返回,不恢复现场(因为要修改board);
                    // 如果是false就恢复现场(这个方法很巧妙)
                    if (dfs(board, x, y + 1)) return true; 
                    board[x][y] = '.';
                    row[x][i] = col[y][i] = cell[x / 3][y / 3][i] = 0;
    
                }
            }
            return false;
        }
    

    相关文章

      网友评论

          本文标题:DFS

          本文链接:https://www.haomeiwen.com/subject/kkorrktx.html