现有一个 3x3 规格的 Android 智能手机锁屏程序和两个正整数 m 和 n ,请计算出使用最少m 个键和最多 n个键可以解锁该屏幕的所有有效模式总数。
其中有效模式是指:
1、每个模式必须连接至少m个键和最多n个键;
2、所有的键都必须是不同的;
3、如果在模式中连接两个连续键的行通过任何其他键,则其他键必须在模式中选择,不允许跳过非选择键(如图);
4、顺序相关,单键有效(这里可能跟部分手机不同)。
输入:m,n
代表允许解锁的最少m个键和最多n个键
输出:
满足m和n个键数的所有有效模式的总数
案例
输入m=1,n=2,表示最少1个键,最多2个键,符合要求的键数是1个键和2个键,其中1个键的有效模式有9种,两个键的有效模式有56种,所以最终有效模式总数是9+56=65种,最终输出65。
import java.util.*;
public class Solution {
/**
* 实现方案
* @param m int整型 最少m个键
* @param n int整型 最多n个键
* @return int整型
*/
//用来存储两个键相连经过其他键情况
private static int[][] arr = new int[10][10];
//动态初始化boolean数组 默认值为false
private static boolean[] select = new boolean[10];
public int solution (int m, int n) {
// write code here
//三行 1和3连线必须2已经连入
arr[1][3] = arr[3][1] = 2;
arr[4][6] = arr[6][4] = 5;
arr[7][9] = arr[9][7] = 8;
//三竖
arr[1][7] = arr[7][1] = 4;
arr[2][8] = arr[8][2] = 5;
arr[9][3] = arr[3][9] = 6;
//两条对角线
arr[1][9] = arr[9][1] = 5;
arr[3][7] = arr[7][3] = 5;
//用于判断是否可以可以连入 二位数组 int默认值为0 没有跨节点下标为0就是true
select[0] = true;
if (m < 0 || n < m) {
return 0;
}
// 1 3 7 9情况合并 2 4 6 8情况合并 5一种情况
int total = 4 * calculateCount(m ,n, 1, 1) + 4 * calculateCount(m ,n, 2, 1)
+ calculateCount(m ,n, 5, 1);
return total;
}
private static int calculateCount(int min, int max, int start, int len) {
int count = 0;
if (len > max) {
return 0;
}
if (len >= min) {
count++;
}
select[start] = true;
for (int i = 1; i < 10; i++) {
//当前节点start没有被选人 并且开始节点start到当前节点i不是跨节点连接
if (!select[i] && select[arr[start][i]]) {
count = count + calculateCount(min, max, i, len + 1);
}
}
select[start] = false;
return count;
}
}