python破解手机锁屏密码_手机屏幕解锁模式

36

可以通过DFS的方式先计算出刚好按下n个键时有多少种组合,然后求出S[n]至S[M]的和。

DFS的主要难度在于,下一步可以与当前的位置不直接相连。这时分两种情况:

1. 普通的八个方向 (上下左右以及其45度夹角方向):

若这八个方向都已经越界或走过了,则这时无路可走。若是普通的DFS则返回,但是九宫格解锁可以跳过相邻的一格。注意只能在这八个方向跳多一步,相当于踩着已经被按下的位置再沿着相同方向走一步。

2.其余的八个方向

其余的八个方向虽然不直接与当前位置直接相连,但是它与当前位置的连线不会触碰到其他位置,因此也可以直接到达。

以下为DFS代码

int dir[16][2] = {//16个方向

{ -1, 0 }, { -1, 1 }, { 0, 1 }, { 1, 1 },

{ 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 },

{-2, 1 }, { -1, 2 }, { 1, 2 }, { 2, 1 },

{ 2, -1 }, { 1, -2 }, { -1, -2 }, { -2, -1 }

};

int isVisit[5][5];//是否已按下

bool canVisit(int i, int j){//判断能否按下

if (i 3 || j 3 || isVisit[i][j]) return false;

return true;

}

int times[10];

//d:已经被选中的键的个数(深度)

void DFS(int i, int j, int d){

if (d == 9){

return;

}

isVisit[i][j] = true;

times[d++] ++;

//选择下一个键

for (int y = 0; y 

int ni = i + dir[y][0], nj = j + dir[y][1];

if (canVisit(ni, nj)){//该点未被选择

DFS(ni, nj, d);

}

else if (y 

ni += dir[y][0];

nj += dir[y][1];

if (canVisit(ni, nj) ){//该点未被选择

DFS(ni, nj, d);

}

}

}

isVisit[i][j] = false;

return;

} solution:

class Solution {

public:

int solution(int m, int n) {

if(m > n){    //易被忽略

return 0;

}

m = (m<0? 0: m);    //参数检查必须有

n = (n>9? 9:n);

int tmp[] = {0, 9, 56, 320, 1624, 7152, 26016, 72912, 140704, 140704 };

int ans = 0;

for(int i=m; i<=n; i++){

ans += tmp[i];

}

return ans;

}

};

发表于 2020-04-01 21:43:16

回复(5)

8

class Solution {

public:

void move(vector >& board, int i, int j, int k, int m, int n, int& ans){

// 如果已经走过的点数大于等于m,则是有效路径,ans++

if(k >= m) ans ++;

// 如果已经走过的点数等于n,则不需要继续探索,故返回

if(k == n) return;

// 如果已经走过的点数小于n,则还可以继续探索

for(int dx=-2; dx<=2; dx++){

for(int dy=-2; dy<=2; dy++){

if(i+dx>=0 && i+dx<=2 && j+dy>=0 && j+dy<=2 && board[i+dx][j+dy]==0){

// 如果两点之间没有第三个点(条件:dx%2 || dy%2),则无需判断是否经过“已经过”的点

// 如果两点之间有第三个点,则需要判断这个点是否是已经走过的点

if(dx%2 || dy%2 || (!(dx%2) && !(dy%2) && board[i+dx/2][j+dy/2]==1)){

board[i+dx][j+dy] = 1;

move(board, i+dx, j+dy, k+1, m, n, ans);

board[i+dx][j+dy] = 0;

}

}

}

}

return;

}

int solution(int m, int n) {

// write code here

vector > board(3, vector(3, 0));

int ans = 0;

// 如果n等于0,则直接返回0

if(n == 0) return ans;

// 选择棋盘上任意一点作为起点

for(int i=0; i<3; i++){

for(int j=0; j<3; j++){

board[i][j] = 1;

move(board, i, j, 1, m, n, ans);

board[i][j] = 0;

}

}

return ans;

}

};

发表于 2020-04-21 19:06:47

回复(2)

12

# Python3 dfs

# 所有方向

di = [(1,0), (-1,0), (0,1), (0,-1), (1,1), (-1,-1), (1,-1), (-1,1), (1,2), (1,-2), (-1,2), (-1,-2), (2,1), (2,-1),(-2,1),(-2,-1)]

# 可跨一个点的方向

ds = [(1,0), (-1,0), (0,1), (0,-1), (1,1), (-1,-1), (1,-1), (-1,1)]

# 9个点

nodes = {(0,0), (0,1), (0,2), (1,0), (1,1), (1,2), (2,0), (2,1), (2,2)}

def dfs(x, y, visited, count):

visited.add((x, y))

count -= 1

ans = 0

if count == 0:

ans += 1

else:

for d in di:

if (x+d[0], y+d[1]) in visited or (x+d[0], y+d[1]) not in nodes:

if d not in ds:

continue

else:

dx = d[0] * 2

dy = d[1] * 2

if (x+dx, y+dy) in nodes and (x+dx, y+dy) not in visited:

ans += dfs(x+dx, y+dy, visited, count)

else:

ans += dfs(x+d[0], y+d[1], visited, count)

visited.remove((x, y))

return ans

ans = [0] * 10

for count in range(1, 10):

for i in range(3):

for j in range(3):

visited = set()

ans[count] += dfs(i, j, visited, count)

# ans[i]即为i个键的结果数

# ans = [0, 9, 56, 320, 1624, 7152, 26016, 72912, 140704, 140704]

print(ans)

编辑于 2020-04-02 18:52:08

回复(2)

4

Java版本,比较容易想到,但是调试了很多遍。 public static int solution (int m, int n) {

// 递归实现

int count = 0;

n = n>9 ? 9 : n;

for(int i=m;i<=n;i++) {

boolean[][] flags = new boolean[3][3];

for(int j=0;j<3;j++) {

for(int t=0;t<3;t++) {

count += findNext(flags, j, t, 0, i);

}

}

}

return count;

}

public static int findNext(boolean[][] flags,int curRow, int curCol, int steps, int n) {

int count = 0;

steps ++;

flags[curRow][curCol] = true;

// 步数走完返回

if(steps == n)

return 1;

// 如果可以走,那么返回 1

for(int i=0;i<3;i++) {

for(int j=0;j<3;j++) {

if(flags[i][j] == false && canStep(flags, curRow, curCol, i, j)) {

count += findNext(flags, i, j, steps, n);

// 恢复状态

flags[i][j] = false;

}

}

}

flags[curRow][curCol] = false;

return count;

}

public static boolean canStep(boolean[][] flags, int curRow, int curCol, int targetRow, int targetCol) {

// 在同一行

if(curRow == targetRow) {

int low = curCol < targetCol?curCol:targetCol;

if(Math.abs(curCol - targetCol) >1 && flags[curRow][low+1] == false)

return false;

}

// 在同一列

if(curCol == targetCol) {

int low = curRow < targe

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值