android 解锁,规则比较复杂,其中比较复杂的是

1) 从1 到3, 如果要穿越2, 那么2必须已经走过了

| 1 | 2 | 3 |
| 4 | 5 | 6 |
| 7 | 8 | 9 |

2) 这样一个九宫格, 定义里竟然1 可以直接到8 的, 不在“穿越” 的定义里!

直接看穿越的定义: 把穿越的关系 定义在一个 二维数组中, 这是这题比较巧妙地地方, 比如 1 -->3 中间为2, 那么只要 看 visted[steps[1][3]] = visted[2] 是否被访问过即可。
     steps[1][3] = steps[3][1] = 2;
     steps[1][7] = steps[7][1] = 4;
     steps[3][9] = steps[9][3] = 6;
     steps[7][9] = steps[9][7] = 8;   
     steps[1][9] = steps[2][8] = steps[4][6] = steps[3][7] = 5;
     steps[9][1] = steps[8][2] = steps[6][4] = steps[7][3] = 5;

 

分析: 1,3,7,9 是对称的,  2,4,6,8 也是对称的, 5是单独的,  因此只要从 1,3,7,9 中选 1 ,结果 x4, 从 2,4,6,8 中选2 结果x4。  最后结果就是 dfs(1) *4 + dfs(2) *4 + dfs(5) 

tip1 :

给定的 m, n 是一个范围, 在dfs 里直接写不好写, 所以用一个for 循环 调用 dfs 函数, 保证每次深度就一个而不是一个范围。

tip2:  注意起始深度是1, 而不是0, 也就是 

dfs(1,1,len,visted,steps)
因为起点已经算放置一个点了,所起始深度为1.

tip3:
这三行 :
              depth++;
              count+= dfs(i,depth, length,visted,steps);
              depth --

可以直接等于 :   count+= dfs(i,depth+1, length,visted,steps);  注意不能是 count+= dfs(i,depth++, length,visted,steps);

 

递归数: 注意 第一个节点时已经是 depth =1 了。

 



class Solution {
    public int numberOfPatterns(int m, int n) {
     final int DOTS = 10;
     
     int[][] steps = new int[DOTS][DOTS];   
     steps[1][3] = steps[3][1] = 2;
     steps[1][7] = steps[7][1] = 4;
     steps[3][9] = steps[9][3] = 6;
     steps[7][9] = steps[9][7] = 8;   
     steps[1][9] = steps[2][8] = steps[4][6] = steps[3][7] = 5;
     steps[9][1] = steps[8][2] = steps[6][4] = steps[7][3] = 5;
        
     boolean[] visted = new boolean[DOTS];
     visted[0] = true; // 剩下的所有steps 都可以直接到达, 注意1-->8 是可以直接穿越的。
     
     int count = 0;   
     for(int len = m; len<=n; len++){
         count += 4* dfs(1,1,len,visted,steps) + 4* dfs(2,1,len,visted,steps) + dfs(5,1,len,visted,steps);    
     }
      
     return count;     
    }
    
    private int dfs( int start,int depth, int length, boolean[] visted,int[][] steps){
        int count=0;
        
        if(depth == length) {
            return 1;
        }
        if(depth >length) return 0;
       
        
        visted[start] = true;
        for(int i =1; i<=9; i++){
            if(!visted[i] && visted[steps[start][i]] ){ // i 没有被访问, 且 visted[穿越] 已经被访问了 
              depth++;
              count+= dfs(i,depth, length,visted,steps);
              depth --;  
            }
            
        }
        
        visted[start] = false;
        
        return count;
        
    }
}

 

那如果不用 for 循环, 直接给dfs 里传 m, n的写法:

tip: 得在  这个条件里直接 count++, 不能在这里return, return 的条件只能是 depth >n 

if(depth >=m && depth<=n)  count++;
class Solution {
    public int numberOfPatterns(int m, int n) {
     final int DOTS = 10;
     
     int[][] steps = new int[DOTS][DOTS];   
     steps[1][3] = steps[3][1] = 2;
     steps[1][7] = steps[7][1] = 4;
     steps[3][9] = steps[9][3] = 6;
     steps[7][9] = steps[9][7] = 8;   
     steps[1][9] = steps[2][8] = steps[4][6] = steps[3][7] = 5;
     steps[9][1] = steps[8][2] = steps[6][4] = steps[7][3] = 5;
        
     boolean[] visted = new boolean[DOTS];
     visted[0] = true; // 剩下的所有steps 都可以直接到达, 注意1-->8 是可以直接穿越的。
        
      
     return 4* dfs(1,1,m,n,visted,steps) + 4* dfs(2,1,m,n,visted,steps) + dfs(5,1,m,n,visted,steps);    
    }
    
    private int dfs( int start,int depth, int m, int n, boolean[] visted,int[][] steps){
        int count = 0;
        if(depth >n) return count;
        if(depth >=m && depth<=n)  count++;
      
        
       
        visted[start] = true;
        for(int i =1; i<=9; i++){
            if(!visted[i] && visted[steps[start][i]] ) // i 没有被访问, 且 visted[穿越] 已经被访问了 
            count += dfs(i,depth+1, m,n,visted,steps);
        }
        
        visted[start] = false;
        
        return count;
        
    }
}

 

posted on 2018-11-22 16:00  KeepAC  阅读(226)  评论(0编辑  收藏  举报