找回密码
 欢迎注册
楼主: wayne

[提问] 关于android手机图案锁屏的计数

[复制链接]
 楼主| 发表于 2013-6-24 14:17:57 | 显示全部楼层
20# gogdizzy 我之前跟你有同样的质疑, 目前也还没深入看 无心大神的 代码,猜想是做了标记。 从跑的结果来看,无心人没有错,所以 能计算出所有合法的情况。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2013-6-24 14:46:56 | 显示全部楼层
21# wayne 跑了一下无心人的程序,结果中确实没有5 2 7 3 4 wayne确认一下这个序列是合法的吗? 如果是合法的,那么就有可能你俩都错了。反倒是你之前给的结果数目较多,有可能正确。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2013-6-24 15:00:30 | 显示全部楼层
22# gogdizzy 是合法的。 那我再看看我的代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2013-6-24 15:21:55 | 显示全部楼层
我修改了一下无心人的代码,添加了一个next2的数组,这个数组用来查找跳跃关系, 例如next2[1]
  • = 3,2,3,5,9,4,7,0,0,0, 表示对于1,有3种跳跃可能,当2被mask了,就可以跳到3,当5被mask了,就可以跳到9,当4被mask了,就可以跳到7. 代码如下:
    1. #include <stdio.h>
    2. int mask[10] = {1,0,0,0,0,0,0,0,0,0};
    3. int next[10][10] =
    4. {0,0,0,0,0,0,0,0,0,0,
    5. 5,2,4,5,6,8,0,0,0,0,
    6. 7,1,3,4,5,6,7,9,0,0,
    7. 5,2,4,5,6,8,0,0,0,0,
    8. 7,1,2,3,5,7,8,9,0,0,
    9. 8,1,2,3,4,6,7,8,9,0,
    10. 7,1,2,3,5,7,8,9,0,0,
    11. 5,2,4,5,6,8,0,0,0,0,
    12. 7,1,3,4,5,6,7,9,0,0,
    13. 5,2,4,5,6,8,0,0,0,0,
    14. };
    15. int next2[10][10] = {
    16. 0,0,0,0,0,0,0,0,0,0,
    17. 3,2,3,5,9,4,7,0,0,0,
    18. 1,5,8,0,0,0,0,0,0,0,
    19. 3,2,1,5,7,6,9,0,0,0,
    20. 1,5,6,0,0,0,0,0,0,0,
    21. 0,0,0,0,0,0,0,0,0,0,
    22. 1,5,4,0,0,0,0,0,0,0,
    23. 3,4,1,5,3,8,9,0,0,0,
    24. 1,5,2,0,0,0,0,0,0,0,
    25. 3,6,3,5,1,8,7,0,0,0,
    26. };
    27. int counter[10] = {0,0,0,0,0,0,0,0,0,0};
    28. int graph[10] = {0,0,0,0,0,0,0,0,0,0};
    29. int nextNumber = 0;
    30. int graphPostion = 0;
    31. void circle( int graphPostion )
    32. {
    33. int i, k;
    34. int noPostion = 1;
    35. int n = graph[graphPostion - 1];
    36. for (i = 1; i <= next[n][0]; i ++)
    37. {
    38. if (mask[next[n][i]] == 0)
    39. {
    40. noPostion = 0;
    41. mask[next[n][i]] = 1;
    42. graph[graphPostion] = next[n][i];
    43. counter[graphPostion + 1] ++;
    44. printf( "find%d: ", graphPostion + 1 );
    45. for( int z = 0; z < graphPostion + 1; ++z ) printf( "%d ", graph[z] );
    46. puts( "" );
    47. circle( graphPostion + 1 );
    48. mask[next[n][i]] = 0;
    49. }
    50. }
    51. for (i = 1, k = 1; i <= next2[n][0]; i ++, k += 2) {
    52. if (mask[next2[n][k]] == 1 && mask[next2[n][k+1]] == 0 ) {
    53. mask[next2[n][k+1]] = 1;
    54. graph[graphPostion] = next2[n][k+1];
    55. counter[graphPostion + 1] ++;
    56. printf( "2find%d: ", graphPostion + 1 );
    57. for( int z = 0; z < graphPostion + 1; ++z ) printf( "%d ", graph[z] );
    58. puts( "" );
    59. circle( graphPostion + 1 );
    60. mask[next2[n][k+1]] = 0;
    61. }
    62. }
    63. }
    64. void first( void )
    65. {
    66. int i;
    67. for (i = 1; i <= 9 ; i ++)
    68. {
    69. mask[i] = 1;
    70. graph[graphPostion] = i;
    71. counter[graphPostion+1] ++;
    72. circle( graphPostion + 1 );
    73. mask[i] = 0;
    74. }
    75. }
    76. int main ( void )
    77. {
    78. int i;
    79. first( );
    80. for (i = 1; i <= 9; i ++)
    81. printf("%d: %d\n", i, counter[i]);
    82. return 0;
    83. }
    复制代码
    最后运行结果: 1: 9 2: 56 3: 320 4: 1624 5: 7152 6: 26016 7: 72912 8: 140704 9: 140704 和你最开始给的答案一致。
  • 评分

    参与人数 1威望 +12 金币 +12 贡献 +12 经验 +12 鲜花 +12 收起 理由
    wayne + 12 + 12 + 12 + 12 + 12 太意外了!

    查看全部评分

    毋因群疑而阻独见  毋任己意而废人言
    毋私小惠而伤大体  毋借公论以快私情
     楼主| 发表于 2013-6-24 16:25:20 | 显示全部楼层
    24# gogdizzy 16# 代码做了一点点的改动,跟楼上的gogdizzy 结果对上了,也跟我最开始的结果对上了。, 所以,我也知道我和无心人错在哪了。 有时候结果一致,不一定就是正确的哈,
    1. PointsToBeChecked[{{a_,b_},{c_,d_}}]:=Module[{g=GCD[c-a,d-b]},If[g>1,{a+# (c-a)/g,b+# (d-b)/g}&/@Range[g-1],{}]];
    2. n=3;ddd=Flatten[Table[{{i,j}},{i,0,n-1},{j,0,n-1}],1];
    3. bb=Table[{ii,Product[n^2-k,{k,0,ii-1}],ddd=Select[Flatten[Table[Join[ii,List@#]&/@Complement[Flatten[Array[List,{n,n}]-1,1],ii],{ii,ddd}],1],Length[Complement[PointsToBeChecked[#[[-2;;-1]]],#[[1;;-3]]]]==0&];Length[ddd]},{ii,2,n^2}]
    复制代码
    毋因群疑而阻独见  毋任己意而废人言
    毋私小惠而伤大体  毋借公论以快私情
     楼主| 发表于 2013-6-24 16:34:21 | 显示全部楼层
    gogdizzy , 有木有兴趣试试 4×4的情况
    毋因群疑而阻独见  毋任己意而废人言
    毋私小惠而伤大体  毋借公论以快私情
     楼主| 发表于 2013-6-24 16:36:22 | 显示全部楼层
    17# wayne 更正如下,求核对: 2,172 3,1744 4,16880 5,154680 6,1331944 7,10690096 后面的,我的改进版的程序也还是力不从心了, 在我2G内存的工作电脑上,Mathematica 抱怨:
    1. No more memory available.
    2. Mathematica kernel has shut down.
    3. Try quitting other applications and then retry.
    复制代码
    毋因群疑而阻独见  毋任己意而废人言
    毋私小惠而伤大体  毋借公论以快私情
    发表于 2013-7-1 15:15:46 | 显示全部楼层
    wayne 发表于 2013-6-24 16:34
    gogdizzy ,
    有木有兴趣试试 4×4的情况


    哎,刚才试了一下,根本就算不过来,因为即使不考虑跳跃,每个数周围平均大概有10个可以连的。否则可能性更多,而最长的一条线应该是16个都用上,那就是10^15量级的搜索量,如果考虑跳跃,就是(10+x)^15了。我这里修改了一个通用程序,然后在circle里做了剪枝(超过一定长度就不计算了),结果如下:
    1 : 16
    2 : 172
    3 : 1744
    4 : 16880
    5 : 154680
    6 : 1331944
    7 : 10690096
    ======添加一个结果=======
    8 : 79137824
    9 : 533427944
    10 : 3221413136
    11 : 17068504632     // 这个算了一个小时,再长一位可能又要增加10倍时间了。
    12 : 77129797424
    13 : 285415667080

    推荐


    程序代码:
    1. #include <cstdio>
    2. #include <vector>

    3. using namespace std;

    4. #define  LEN  4
    5. #define  PTS  (LEN * LEN)

    6. int mask[PTS] = {0};
    7. int counter[PTS+1] = {0};
    8. int graph[PTS] = {0};
    9. int neibNumber = 0;
    10. int graphPostion = 0;
    11. vector< int > neib[LEN][PTS];

    12. int  gcd( int a, int b ) {
    13.         int  t;
    14.         while( b ) {
    15.                 t = a % b;
    16.                 a = b;
    17.                 b = t;
    18.         }
    19.         return  a;
    20. }

    21. void  init_neib() {

    22.         // init counter
    23.         for( int i = 0; i < LEN; ++i )
    24.                 for( int j = 0; j < PTS; ++j ) {
    25.                         neib[i][j].clear();
    26.                         neib[i][j].push_back( 0 );
    27.                 }

    28. #define  XY2IDX( r, c ) ( ( r ) * LEN + ( c ) )
    29. #define  CHECK( r0, c0, r1, c1 ) \
    30.         do {    int  rd = abs( r0 - r1 ); \
    31.         int  cd = abs( c0 - c1 ); \
    32.         int  gd = gcd( rd, cd ); \
    33.         int  rs = ( r1 - r0 ) / gd; \
    34.         int  cs = ( c1 - c0 ) / gd; \
    35.         int  idx0 = XY2IDX( r0, c0 ); \
    36.         int  idx1 = XY2IDX( r1, c1 ); \
    37.         for( int i = 1; i <= gd; ++i ) neib[gd][idx0].push_back( XY2IDX( r0 + i * rs, c0 + i * cs ) ); \
    38.         ++neib[gd][idx0][0]; \
    39.         rs = -rs; cs = -cs; \
    40.         for( int i = 1; i <= gd; ++i ) neib[gd][idx1].push_back( XY2IDX( r1 + i * rs, c1 + i * cs ) ); \
    41.         ++neib[gd][idx1][0]; \
    42.         } while(0)

    43.         int  r0, c0, r1, c1;
    44.         for( r0 = 0; r0 < LEN; ++r0 ) {
    45.                 for( c0 = 0; c0 < LEN; ++c0 ) {
    46.                         for( r1 = r0; r1 < LEN; ++r1 ) {
    47.                                 for( c1 = ( r1 == r0 ? c0 + 1 : 0 ); c1 < LEN; ++c1 ) {
    48.                                         CHECK( r0, c0, r1, c1 );
    49.                                 }
    50.                         }
    51.                 }
    52.         }
    53. }

    54. void  circle( int pos ) {
    55.         if( pos > 6 ) return; // 剪枝了,计算量太大。
    56.         int  i, j, k, step;
    57.         bool ok;
    58.         int  n = graph[pos-1];
    59.         for( step = 1; step < LEN; ++step ) {
    60.                 for( i = 0, k = 1; i < neib[step][n][0]; ++i, k += step ) {
    61.                         ok = true;
    62.                         for( j = 0; j < step - 1; ++j )
    63.                                 if( mask[ neib[step][n][k+j] ] == 0 ) { ok = false; break; }
    64.                         if( ok && mask[ neib[step][n][k+step-1] ] == 0 ) {
    65.                                 mask[ neib[step][n][k+step-1] ] = 1;
    66.                                 {
    67.                                         graph[pos] = neib[step][n][k+step-1];
    68.                                         counter[pos+1]++;
    69.                                         circle( pos + 1 );
    70.                                 }
    71.                                 mask[ neib[step][n][k+step-1] ] = 0;
    72.                         }
    73.                 }
    74.         }
    75. }

    76. void  first() {
    77.         int  i;
    78.         for( i = 0; i < PTS; ++i ) {
    79.                 mask[i] = 1;
    80.                 {
    81.                         graph[graphPostion] = i;
    82.                         counter[graphPostion + 1]++;
    83.                         circle( graphPostion + 1 );
    84.                 }
    85.                 mask[i] = 0;
    86.         }
    87. }

    88. void  print_vec( vector< int > & x ) {
    89.         for( int i = 0; i < x.size(); ++i ) {
    90.                 printf( "%d ", x[i] );
    91.         }
    92.         puts( "" );
    93. }

    94. int main ( void )
    95. {
    96.         init_neib();
    97.         //for( int i = 1; i < LEN; ++i ) {
    98.         //        for( int j = 0; j < PTS; ++j ) print_vec( neib[i][j] );
    99.         //        puts( "" );
    100.         //}
    101.        
    102.         first();
    103.         for( int i = 0; i <= PTS; ++i ) {
    104.                 printf( "%d : %d\n", i, counter[i] );
    105.         }
    106.         return 0;
    107. }
    复制代码
    补充内容 (2013-7-2 09:31):
    12 : 77129797424

    补充内容 (2013-7-2 17:10):
    代码里的counter数组用了int,会溢出,后来改成int64了。

    补充内容 (2013-7-3 09:57):
    如果考虑对称关系,可以提速。只需要计算1/8个象限内的起始点就可以了,当然因为对角线上的点必需计算,所以计算量略多于1/8。

    补充内容 (2013-7-3 13:09):
    13 : 285415667080          // 用了对称关系,所以这个结果也在几个小时内计算出来了。

    评分

    参与人数 1威望 +12 金币 +12 贡献 +12 经验 +12 鲜花 +12 收起 理由
    wayne + 12 + 12 + 12 + 12 + 12 很给力!

    查看全部评分

    毋因群疑而阻独见  毋任己意而废人言
    毋私小惠而伤大体  毋借公论以快私情
     楼主| 发表于 2013-7-1 16:05:09 | 显示全部楼层
    gogdizzy 发表于 2013-7-1 15:15
    哎,刚才试了一下,根本就算不过来,因为即使不考虑跳跃,每个数周围平均大概有10个可以连的。否则可能 ...


    看到程序里的CHECK宏函数了,看来跟我的思路是一样的。
    毋因群疑而阻独见  毋任己意而废人言
    毋私小惠而伤大体  毋借公论以快私情
    发表于 2013-8-23 21:53:17 | 显示全部楼层
    在我的代码里,不存在7-3的链接,
    因为,7-3必定过5,是不存在的

    不过我刚验证了你说的情况
    可能是我还是没理解这个图案的禁断的判定吧
    毋因群疑而阻独见  毋任己意而废人言
    毋私小惠而伤大体  毋借公论以快私情
    您需要登录后才可以回帖 登录 | 欢迎注册

    本版积分规则

    小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

    GMT+8, 2024-12-23 18:24 , Processed in 0.025969 second(s), 16 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表