zoukankan      html  css  js  c++  java
  • 九宫格密码组合计数问题

    问题简述:

      Android的九宫格密码想必大家都见过了。
      大于等于四个点相连便可以作为一种密码。
      那么九宫格密码有多少种?

    算法简述:

      关键词: 组合 排列 动态规划

      Android 的密码是 3 × 3 点阵中的一条路径,这条路径可以交叉,可以“走日字”,几乎是无所不能(只要不经过重复点),但却有一个例外:路径不允许跳过途中必须要经过     的点。例如, 如果从左上角的点连接到右上角的点,中间的那个点会被自动地加进路径里。但麻烦就麻烦在,这个规则本身也有一个值得注意的地方:如果中间的点是之前已经用过的,那么这个点就可以被跳过去了。

    /gkimage/e8/kt/3e/e8kt3e.png

    我们不妨把点阵中的九个点分别用数字 1 到 9 编号。按照上述规则,4136、4192 都是不合法的,但 24136、654192 则都是可行的。

    算法思路参考:http://www.guokr.com/article/49408/

    即:斜线有8条,共8对数字:  1-3前有2  1-7需有4  1-9需有5  2-8需有5

                                3-7需有5  3-9需有6  4-6需有5  7-9需有8  否则为失败

    所以:通过动态规划遍历排列并验证(首先若i个数组合的某序列为失败,则其衍生出的后续i+1个数组合的某序列也为失败,故而不再验证,即也不会再向后动态迭代)

    代码运行可知:

        

    密码长度 1 2 3 4 5 6 7 8 9 总计
    密码个数 9 56 320 1624 7152 26016 72912 140704 140704 389497

         

                九宫格密码大于等于四位,故九宫格密码共有389212种,密码最好设置6位及6位以上。

    代码如下:

      1 package 九宫格;
      2 
      3 public class Main{
      4 
      5     public static void main(String[] argv){
      6         
      7         // 计算组合数
      8         int k[] = new int[9];
      9         int p_count[] = new int[9];
     10         int sum=0;
     11         int Out_result=0;
     12         
     13         for(int i=0; i<9;i++){
     14             
     15             if(i==0){
     16                 k[i]=9; p_count[i]=1;
     17             }
     18                 
     19             else{
     20                 k[i]=k[i-1]*(9-i);
     21             }
     22             if(i>=3)
     23                 sum=sum+k[i];
     24         }        
     25         System.out.println(sum);
     26         
     27         //计算排列
     28         int [][] middle = new int[9][1];
     29         
     30         for(int i=0; i<9;i++){
     31             
     32             int n = k[i];
     33             int N = p_count[i];
     34             int mid_out[][] = new int[n][i+1];
     35             int pai_out[][] = new int[N][i+1];
     36             int j=0;
     37             if(i==0){
     38                 
     39                 for(; j<N; j++ )
     40                     pai_out[j][0]=0;
     41                 j=0;
     42                 for(; j<n; j++)
     43                     mid_out[j][0]=j+1;
     44                 j=0;
     45                 //更新上一次的可行序列数
     46                 k[i]=9;
     47             }
     48             else{
     49                 
     50                 // 获取排列    
     51 
     52                 for(int t=0; t<k[i-1]; t++){
     53                     
     54                     int check[] =new int[10];
     55                     for(int m=0; m<i;m++){
     56                         
     57                         check[middle[t][m]]=1;
     58                         
     59                     }
     60                     for(int p=1; p<=9; p++ ){
     61                         
     62                         if(check[p]!=1){
     63                             
     64                         //排列验证成功则加入到序列中
     65                         if(check_Success(middle[t][i-1],p,check)){
     66                                                     
     67                             for(int m=0; m<i;m++){                            
     68                             mid_out[j][m]=middle[t][m];                                                        
     69                                 }
     70                         
     71                         mid_out[j][i]=p;
     72                         j++;
     73                             }
     74                         
     75                         }
     76                         
     77                     }
     78                     
     79                     
     80                 }
     81                 //更新上一次的可行序列数
     82                 k[i]=j;
     83             }
     84             if(i>2)
     85             Out_result=Out_result+k[i];
     86             middle = new int[n][i+1];
     87             middle = mid_out;
     88             for(int count_x=0; count_x<j; count_x++){
     89                 System.out.print((count_x+1)+"th: ");
     90                 for(int count_y=0; count_y<=i;count_y++)
     91                     System.out.print(mid_out[count_x][count_y]+" ");
     92                 System.out.println();
     93             }
     94             System.out.println("The"+i+"th result as..."+j);
     95             
     96             
     97         }
     98         
     99         System.out.println("The result is:"+Out_result);
    100         for(int i=0; i<9; i++){
    101             
    102             System.out.println(k[i]);
    103         }
    104     }
    105 
    106     public static boolean check_Success(int a, int b, int[] r){
    107         
    108         int[][] k_table = new int[10][10];
    109         // init...
    110         k_table[1][3]=2; k_table[3][1]=2; 
    111         k_table[1][7]=4; k_table[7][1]=4; 
    112         k_table[1][9]=5; k_table[9][1]=5;
    113         // init....
    114         k_table[2][8]=5; k_table[8][2]=5; 
    115         //init....
    116         k_table[3][7]=5; k_table[7][3]=5; 
    117         k_table[3][9]=6; k_table[9][3]=6; 
    118         // init....
    119         k_table[4][6]=5; k_table[6][4]=5; 
    120         // init....
    121         k_table[7][9]=8; k_table[9][7]=8;
    122         if(k_table[a][b]>0){
    123             if(r[k_table[a][b]]==1)
    124                 return true;
    125             else
    126                 return false;
    127         }
    128         else
    129             return true;
    130         
    131         
    132     }
    133 }
  • 相关阅读:
    Vue 移动端向上滑动加载
    关于NPOI 判断Office 是否为空的操作
    定时任务的处理
    Web中线程与IIS线程池自动回收机制
    本地VS调试服务器 IIS 程序
    每天学点node系列-stream
    聊聊前端模块化开发
    位运算解决多标签问题【原创】
    <未来世界的幸存者> 读后感(现实篇和职业篇)【原创】
    Nest.js你学不会系列-初识Nest
  • 原文地址:https://www.cnblogs.com/udld/p/5008930.html
Copyright © 2011-2022 走看看