手势密码(DFS)

来源:互联网 发布:淘宝冷门类目有哪些 编辑:程序博客网 时间:2024/06/08 04:31

手势密码(DFS)

题目描述

很多手机或平板电脑软件都可以设置手势密码,在设置了手势密码后,进入程序时,首先要输入手势密码。
手势密码最少选择4个点,最多选择9个点,理论上的密码组合总共有985824种,扣除掉其中不可能完成的组合(如一些点不允许绕过),最终的可能性是389112种。可见,手势密码加强了软件访问的安全性。
下面介绍一下手势密码的规则(如果你熟悉手势密码的规则,可略过):
1)  从某一个点出发,不间断地画线连接4-9个点,则从起点至终点构成的有序轨迹便构成一个有效的手势密码。
2)  在水平、垂直及对角方向上的3个点(假设依次为A点、B点、C点),在B点是未选点的情况下,A点是绕不过B点直接与C点相连的,如点1和点3直线连接绕不过点2。同样道理,点1和点9直线连接绕不过点5,等等。如图3所示,如果起点是1点,则手势密码必为1->2->3->6->5->4->7->8->9,而不可能是1->3->6->4->7->9。
3)  在连线不间断延展的过程中,只要还有未选的新点,就可以画线连接到该新点,而不管是否有重叠或是交叉,即经过已选点或已连线均可。例如,2->3->1->5或1->5->2->4都是允许的。
4)  在连线不间断延展的过程中,中间点是不允许经过2次的(除非是规则3说明的情况),终点虽然可以再连接到已选点,但却是无效的。例如,以1点为起点,则图4所示的手势密码跟图3所示的手势密码跟图3所示的手势密码是一样的。
这里写图片描述
解题思路:
1、每次DFS可以看成以进入点为起点,以选择点为终点的路线,并且记录该终点,主函数中应该提早记录哪些点不能够直接到达(需要的中间节点是哪一个),并且做特殊化处理,接下来只需要DFS(),并且记录满足条件的路线即可。

#include <iostream>#include <cstdio>#include <set>#include<cstring>#include<queue>const int  MaxSize =1000000;using namespace std;int able[10][10]={0};int vis[10];int cnt;int max1;int sum;int n;int star;int dfs(int s){  if(sum>max1) return 0;   if(sum>=n&&sum<=max1)    {        cnt++;    }   for(int i=1;i<=9;i++)     {        if((!able[s][i]||vis[able[s][i]])&&vis[i]!=1)        {   //cout<<"s="<<s<<",i="<<i<<endl;            sum++;            vis[i]=1;            dfs(i);            sum--;            vis[i]=0;        }     }     return 0;}int main(){able[1][3]=2; able[3][1]=2; able[1][9]=5; able[9][1]=5; able[1][7]=4; able[7][1]=4; able[3][7]=5; able[7][3]=5; able[7][9]=8; able[9][7]=8; able[3][9]=6; able[9][3]=6; able[2][8]=5; able[8][2]=5; able[4][6]=5; able[6][4]=5; //for(int i=1;i<=9;i++) able[i][i]=1; while(scanf("%d%d",&n,&max1)==2) {   sum=0;     cnt =0;     memset(vis,0,sizeof(vis));     dfs(0);     printf("%d\n",cnt); }}