现有一个 3x3 规格的 Android 智能手机锁屏程序和两个正整数 m 和 n ,请计算出使用最少m 个键和最多 n个键可以解锁该屏幕的所有有效模式总数。
其中有效模式是指:
1、每个模式必须连接至少m个键和最多n个键;
2、所有的键都必须是不同的;
3、如果在模式中连接两个连续键的行通过任何其他键,则其他键必须在模式中选择,不允许跳过非选择键(如图);
4、顺序相关,单键有效(这里可能跟部分手机不同)。
输入:m,n
代表允许解锁的最少m个键和最多n个键
输出:
满足m和n个键数的所有有效模式的总数
输入例子1:
1,2
输出例子1:
65
例子说明1:
输入m=1,n=2,表示最少1个键,最多2个键,符合要求的键数是1个键和2个键,其中1个键的有效模式有9种,两个键的有效模式有56种,所以最终有效模式总数是9+56=65种,最终输出65。
class Solution {
public:
/**
* 实现方案
* @param m int整型 最少m个键
* @param n int整型 最多n个键
* @return int整型
*/
int res=0;
//board:棋盘 (i,j)起始点 idx已访问的点数
void search(vector<vector<int>>board,int i,int j,int idx,int m,int n)
{
if(idx>=m) res++;
if(idx>=n) return;//递归返回条件
//一个点向四周的走法有24种情况,构成5x5矩阵
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)
{
//两点连接不经过中间点16种情况,直接搜索即可
//经过中间点,需要保证中间点已经被访问
if(dx%2 || dy%2 || (!(dx%2) && !(dy%2) && board[i+dx/2][j+dy/2]==1))
{
board[i+dx][j+dy]=1;
search(board,i+dx,j+dy,idx+1,m,n);
board[i+dx][j+dy]=0;
}
}
}
}
return;
}
int solution(int m, int n) {
// write code here
if(m>n||n<=0) return 0;
vector<vector<int>>board(3,vector<int>(3,0));
//任何点都可以为起始点
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
//起始点访问,置1
board[i][j]=1;
search(board,i,j,1,m,n);
//回溯,以下一个任一点为起点时,刚才访问的点状态复原
board[i][j]=0;
}
}
return res;
}
};