wayne 发表于 2013-6-24 14:17:57

20# gogdizzy
我之前跟你有同样的质疑,
目前也还没深入看 无心大神的 代码,猜想是做了标记。

从跑的结果来看,无心人没有错,所以 能计算出所有合法的情况。

gogdizzy 发表于 2013-6-24 14:46:56

21# wayne

跑了一下无心人的程序,结果中确实没有5 2 7 3 4
wayne确认一下这个序列是合法的吗?
如果是合法的,那么就有可能你俩都错了。反倒是你之前给的结果数目较多,有可能正确。

wayne 发表于 2013-6-24 15:00:30

22# gogdizzy
是合法的。

那我再看看我的代码

gogdizzy 发表于 2013-6-24 15:21:55

我修改了一下无心人的代码,添加了一个next2的数组,这个数组用来查找跳跃关系,
例如next2[*] = 3,2,3,5,9,4,7,0,0,0,
表示对于1,有3种跳跃可能,当2被mask了,就可以跳到3,当5被mask了,就可以跳到9,当4被mask了,就可以跳到7.

代码如下:
#include <stdio.h>

int mask = {1,0,0,0,0,0,0,0,0,0};
int next =
{0,0,0,0,0,0,0,0,0,0,
5,2,4,5,6,8,0,0,0,0,
7,1,3,4,5,6,7,9,0,0,
5,2,4,5,6,8,0,0,0,0,
7,1,2,3,5,7,8,9,0,0,
8,1,2,3,4,6,7,8,9,0,
7,1,2,3,5,7,8,9,0,0,
5,2,4,5,6,8,0,0,0,0,
7,1,3,4,5,6,7,9,0,0,
5,2,4,5,6,8,0,0,0,0,
};
int next2 = {
0,0,0,0,0,0,0,0,0,0,
3,2,3,5,9,4,7,0,0,0,
1,5,8,0,0,0,0,0,0,0,
3,2,1,5,7,6,9,0,0,0,
1,5,6,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
1,5,4,0,0,0,0,0,0,0,
3,4,1,5,3,8,9,0,0,0,
1,5,2,0,0,0,0,0,0,0,
3,6,3,5,1,8,7,0,0,0,
};


int counter = {0,0,0,0,0,0,0,0,0,0};
int graph = {0,0,0,0,0,0,0,0,0,0};
int nextNumber = 0;
int graphPostion = 0;

void circle( int graphPostion )
{
int i, k;
int noPostion = 1;
int n = graph;
for (i = 1; i <= next; i ++)
{
    if (mask] == 0)
      {
          noPostion = 0;
          mask] = 1;
            graph = next;
          counter ++;
          printf( "find%d: ", graphPostion + 1 );
          for( int z = 0; z < graphPostion + 1; ++z ) printf( "%d ", graph );
          puts( "" );
          circle( graphPostion + 1 );
          mask] = 0;
      }
}

for (i = 1, k = 1; i <= next2; i ++, k += 2) {
    if (mask] == 1 && mask] == 0 ) {
      mask] = 1;
                graph = next2;
                counter ++;
          printf( "2find%d: ", graphPostion + 1 );
          for( int z = 0; z < graphPostion + 1; ++z ) printf( "%d ", graph );
          puts( "" );
                circle( graphPostion + 1 );
      mask] = 0;
    }
}

}

void first( void )
{
int i;
for (i = 1; i <= 9 ; i ++)
{
    mask = 1;
      graph = i;
      counter ++;
      circle( graphPostion + 1 );
    mask = 0;
}
}

int main ( void )
{
int i;
first( );
for (i = 1; i <= 9; i ++)
    printf("%d: %d\n", i, counter);
return 0;
}
最后运行结果:
1: 9
2: 56
3: 320
4: 1624
5: 7152
6: 26016
7: 72912
8: 140704
9: 140704

和你最开始给的答案一致。

wayne 发表于 2013-6-24 16:25:20

24# gogdizzy
对16# 代码做了一点点的改动,跟楼上的gogdizzy结果对上了,也跟我最开始的结果对上了。,:handshake
所以,我也知道我和无心人错在哪了。
有时候结果一致,不一定就是正确的哈,:lolPointsToBeChecked[{{a_,b_},{c_,d_}}]:=Module[{g=GCD},If,{}]];
n=3;ddd=Flatten,1];
bb=Table[{ii,Product,ddd=Select&/@Complement-1,1],ii],{ii,ddd}],1],Length]],#[]]]==0&];Length},{ii,2,n^2}]

wayne 发表于 2013-6-24 16:34:21

gogdizzy ,:victory:
有木有兴趣试试 4×4的情况

wayne 发表于 2013-6-24 16:36:22

17# wayne
更正如下,求核对:
2,172
3,1744
4,16880
5,154680
6,1331944
7,10690096
后面的,我的改进版的程序也还是力不从心了,
在我2G内存的工作电脑上,Mathematica 抱怨:No more memory available.
Mathematica kernel has shut down.
Try quitting other applications and then retry.

gogdizzy 发表于 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

最前沿的结果

程序代码:#include <cstdio>
#include <vector>

using namespace std;

#defineLEN4
#definePTS(LEN * LEN)

int mask = {0};
int counter = {0};
int graph = {0};
int neibNumber = 0;
int graphPostion = 0;
vector< int > neib;

intgcd( int a, int b ) {
        intt;
        while( b ) {
                t = a % b;
                a = b;
                b = t;
        }
        returna;
}

voidinit_neib() {

        // init counter
        for( int i = 0; i < LEN; ++i )
                for( int j = 0; j < PTS; ++j ) {
                        neib.clear();
                        neib.push_back( 0 );
                }

#defineXY2IDX( r, c ) ( ( r ) * LEN + ( c ) )
#defineCHECK( r0, c0, r1, c1 ) \
        do {    intrd = abs( r0 - r1 ); \
        intcd = abs( c0 - c1 ); \
        intgd = gcd( rd, cd ); \
        intrs = ( r1 - r0 ) / gd; \
        intcs = ( c1 - c0 ) / gd; \
        intidx0 = XY2IDX( r0, c0 ); \
        intidx1 = XY2IDX( r1, c1 ); \
        for( int i = 1; i <= gd; ++i ) neib.push_back( XY2IDX( r0 + i * rs, c0 + i * cs ) ); \
        ++neib; \
        rs = -rs; cs = -cs; \
        for( int i = 1; i <= gd; ++i ) neib.push_back( XY2IDX( r1 + i * rs, c1 + i * cs ) ); \
        ++neib; \
        } while(0)

        intr0, c0, r1, c1;
        for( r0 = 0; r0 < LEN; ++r0 ) {
                for( c0 = 0; c0 < LEN; ++c0 ) {
                        for( r1 = r0; r1 < LEN; ++r1 ) {
                                for( c1 = ( r1 == r0 ? c0 + 1 : 0 ); c1 < LEN; ++c1 ) {
                                        CHECK( r0, c0, r1, c1 );
                                }
                        }
                }
        }
}

voidcircle( int pos ) {
        if( pos > 6 ) return; // 剪枝了,计算量太大。
        inti, j, k, step;
        bool ok;
        intn = graph;
        for( step = 1; step < LEN; ++step ) {
                for( i = 0, k = 1; i < neib; ++i, k += step ) {
                        ok = true;
                        for( j = 0; j < step - 1; ++j )
                                if( mask[ neib ] == 0 ) { ok = false; break; }
                        if( ok && mask[ neib ] == 0 ) {
                                mask[ neib ] = 1;
                                {
                                        graph = neib;
                                        counter++;
                                        circle( pos + 1 );
                                }
                                mask[ neib ] = 0;
                        }
                }
        }
}

voidfirst() {
        inti;
        for( i = 0; i < PTS; ++i ) {
                mask = 1;
                {
                        graph = i;
                        counter++;
                        circle( graphPostion + 1 );
                }
                mask = 0;
        }
}

voidprint_vec( vector< int > & x ) {
        for( int i = 0; i < x.size(); ++i ) {
                printf( "%d ", x );
        }
        puts( "" );
}

int main ( void )
{
        init_neib();
        //for( int i = 1; i < LEN; ++i ) {
        //        for( int j = 0; j < PTS; ++j ) print_vec( neib );
        //        puts( "" );
        //}
       
        first();
        for( int i = 0; i <= PTS; ++i ) {
                printf( "%d : %d\n", i, counter );
        }
        return 0;
}
补充内容 (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          // 用了对称关系,所以这个结果也在几个小时内计算出来了。

wayne 发表于 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,是不存在的

不过我刚验证了你说的情况
可能是我还是没理解这个图案的禁断的判定吧
页: 1 2 [3]
查看完整版本: 关于android手机图案锁屏的计数