LintCode:Android Unlock Patterns

Given an Android 3x3 key lock screen and two integers mand n, where 1 ≤ m ≤ n ≤ 9, count the total number of unlock patterns of the Android lock screen, which consist of minimum of m keys and maximum n keys.

Rules for a valid pattern:
1. Each pattern must connect at least m keys and at most nkeys.
2. All the keys must be distinct.
3. If the line connecting two consecutive keys in the pattern passes through any other keys, the other keys must have previously selected in the pattern. No jumps through non selected key is allowed.
4. The order of keys used matters.
android unlock
Explanation:

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

Invalid move: 4 - 1 - 3 - 6
Line 1 - 3 passes through key 2 which had not been selected in the pattern.

Invalid move: 4 - 1 - 9 - 2
Line 1 - 9 passes through key 5 which had not been selected in the pattern.

Valid move: 2 - 4 - 1 - 3 - 6
Line 1 - 3 is valid because it passes through key 2, which had been selected in the pattern

Valid move: 6 - 5 - 4 - 1 - 9 - 2
Line 1 - 9 is valid because it passes through key 5, which had been selected in the pattern.

 

思路:DFS,1,3,7,9四点对称,2,4,6,8四点对称,还剩一个5,故只需计算1,2,5三个点。对于任意两个点的坐标(x1,y1),(x2,y2),如果((x1+x2)%2==0 && (y1+y2)%2==0),说明两点连线之间存在一个中点((x1+x2)/2, (y1+y2)/2)。如果这个中点被访问过,则这两点是可以连通的;如果中点没有被访问过,则两点不能连通。如果两点间不存在中点,则两点也是可以连通的。

 1 class Solution {
 2 public:
 3     /**
 4      * @param m: an integer
 5      * @param n: an integer
 6      * @return: the total number of unlock patterns of the Android lock screen
 7      */
 8     bool isCanGo(int curi, int curj, int i, int j, vector<vector<bool> > &visited)
 9     {
10         int sum1=curi+curj;
11         int sum2=i+j;
12         if(sum1-sum2==1 || sum2-sum1==1)return true;
13         if((curi+i)%2==0 && (curj+j)%2==0)return visited[(curi+i)/2][(curj+j)/2];
14         return true;
15     }
16     int DFS(int m, int n, int curi, int curj, int len, vector<vector<bool> > &visited)
17     {
18         if(len>n)return 0;
19         int sum=0;
20         if(len>=m && len<=n)++sum;
21         visited[curi][curj]=true;
22         for(int i=0; i<3; ++i)
23         {
24             for(int j=0; j<3; ++j)
25             {
26                 if(curi==i && curj==j)continue;
27                 if(visited[i][j])continue;
28                 if(isCanGo(curi, curj, i, j, visited))sum=sum+DFS(m, n, i, j, len+1, visited);
29             }
30         }
31         visited[curi][curj]=false;
32         return sum;
33     }
34     int numberOfPatterns(int m, int n) {
35         if(m<=0 || n<=0 || m>n)return -1;
36         vector<vector<bool> > visited(3, vector<bool>(3, false));
37         return DFS(m, n, 0, 0, 1, visited)*4+DFS(m, n, 0, 1, 1, visited)*4+DFS(m, n, 1, 1, 1, visited);
38     }
39 };

 

 

 

 

转载于:https://www.cnblogs.com/jeysin/p/8656201.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值