mathe 发表于 2009-10-16 09:20:53

修改后的代码如下:
此外如果内存还是太小,宏STABLE还可以改小一半左右.但是需要注意STABLE和WALK必须互素.// chp.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#define N 8
#define BITS (N*N)
typedef unsigned long long SET;
SET nghb;
#define EMPTY_SET    0LL
#define INDEX(x,y)   ((x)*N+(y))
#define GET_X(ind)   ((ind)/N)
#define GET_Y(ind)   ((ind)%N)
#define ADD_INDEX(s, ind)((s)|=1LL<<(ind))
#define TEST_INDEX(s, ind)(((s)&(1LL<<(ind)))!=0)
#define CORNMASK   (3|(3<<N))
#define TEST_BIT(x, b)   (((x)&(1LL<<(b)))!=0)
#define SET_BIT(x, b)    ((x)|=(1LL<<(b)))

#define GET_CORN(x)(((x)&3)| (((x)>>N)&3)<<2)
#define DISP_CORN(x) (((x)&3)| ((((x)>>2)&3)<<N))
#define ECVALUE(x)   (((x)&~CORNMASK)|DISP_CORN(cr))

#define STABLE 50000033
#define WALK   1000
int hc;
int ec;
int nec;
int lec;
long long htable;
//long long htable2;
char cr={1,-1,-1,-1,-1,-1,-1,-1,4,-1,5,-1,3,-1,11,7};
char rc={-1,0,-1,12,8,10,-1,15,-1,-1,-1,14,-1,-1,-1,-1};

FILE *fout;
void dump(long long v)
{
        int i,j;
        for(i=0;i<N;i++){
                for(j=0;j<N;j++){
                        if(TEST_BIT(v,i*N+j)){
                                fprintf(fout,"1 ");
                        }else{
                                fprintf(fout,"0 ");
                        }
                }
                fprintf(fout,"\n");
        }
        fprintf(fout,"\n");
}

void copy_ec(long long *p)
{
        int i,t;
        for(i=0,t=0;i<STABLE;i++){
                if(htable!=-1LL){
                        if(cr)]!=-1){
                                p=htable;
                        }
                }
        }
}

void dump_ec(long long htable[])
{
        int i;
        fout = fopen("dump.txt","w");
        for(i=0;i<STABLE;i++){
                if(htable!=-1LL){
                        if(cr)]!=-1){
                                dump(htable);
                        }
                }
        }
        fclose(fout);
}

void init()
{
    memset(htable,-1,sizeof(htable));
//        memset(htable2,-1,sizeof(htable2));
}

int hash(SET s)
{
    return (int)(s%STABLE);
}

int add_hash(long long htable[],long long key, bool eq)
{
    int v=hash(key);
    long long ev;
    ev=ECVALUE(key);
    if(hc>=STABLE){
      fprintf(stderr,"out of hash table range\n");
      exit(-1);
    }
    do{
      if(htable==-1LL){
            if(eq){
                htable=ev;nec++;
            }else{
                htable=key;
                                ec++;
            }
            hc++;
            return v;
      }else if(htable!=key&&htable!=ev){
            v=(v+WALK)%STABLE;
      }else{
            if(eq){
                assert(htable==ev);
            }else{
                assert(htable==key);
            }
            return v;
      }
    }while(1);
}

int query_hash_entry(long long htable[],long long key)///return index to hash table
{
    long long ev=ECVALUE(key);
    int v=hash(key);
    do{
      if(htable==-1LL)return v;
      if(htable==key||htable==ev)
            return v;
      v=(v+WALK)%STABLE;
    }while(1);
}

void init_neighbour()
{
    int i,j;
    for(i=0;i<N;i++){
      for(j=0;j<N;j++){
            SET s=EMPTY_SET;
            ADD_INDEX(s,INDEX(i,j));
            if(i>0&&j>0){
                ADD_INDEX(s,INDEX(i-1,j-1));
            }
            if(i>0){
                ADD_INDEX(s,INDEX(i-1,j));
            }
            if(j>0){
                ADD_INDEX(s,INDEX(i,j-1));
            }
            if(i>0&&j<N-1){
                ADD_INDEX(s,INDEX(i-1,j+1));
            }
            if(j<N-1){
                ADD_INDEX(s,INDEX(i,j+1));
            }
            if(i<N-1&&j>0){
                ADD_INDEX(s,INDEX(i+1,j-1));
            }
            if(i<N-1){
                ADD_INDEX(s,INDEX(i+1,j));
            }
            if(i<N-1&&j<N-1){
                ADD_INDEX(s,INDEX(i+1,j+1));
            }
            nghb=s;
      }
    }
}
#if 0
void visit(long long neighb)
{
        int i;
        int e=query_hash_entry(htable,neighb);
        if(htable==neighb){
                int ee=query_hash_entry(htable2,neighb);
                if(htable2==-1){
                        htable2=neighb;
                        lec++;
                        for(i=0;i<BITS;i++){
                                if(TEST_BIT(neighb,i)==0){
                                        long long newneighb=neighb;
                                        newneighb|=nghb;
                                        visit(newneighb);
                                }
                        }
                }
        }else{
                for(i=0;i<BITS;i++){
                        if(TEST_BIT(neighb,i)==0){
                                long long newneighb=neighb;
                                newneighb|=nghb;
                                int e2=query_hash_entry(htable,newneighb);
                                if(htable==newneighb){
                                        visit(newneighb);
                                        break;
                                }
                        }
                }
        }
}
#endif
int query(long long neighb)
{
    int e=query_hash_entry(htable,neighb);
    if(htable!=-1)
      return e;
    int i;
    for(i=0;i<BITS;i++){
      if(TEST_BIT(neighb,i)==0){
            long long newneighb=neighb;
            newneighb|=nghb;
            int r=query(newneighb);
            if(htable==newneighb)
                break;
      }
    }
    if(i<BITS){///find any status is newneighb
      return add_hash(htable,neighb,true);
    }else{
      return add_hash(htable,neighb,false);
    }
}

int cmpll(const void *p,const void *q)
{
        const long long *lp=(const long long *)p;
        const long long *lq=(const long long *)q;
        if(*lp==*lq)return 0;
        if(*lp<*lq)return -1;
        return 1;
}

int _tmain(int argc, _TCHAR* argv[])
{
        int i,j;
    init();
    init_neighbour();
    int s=query(0LL);
    if(htable==0LL){
      printf("First fail\n");
    }else{
      printf("First successful\n");
    }
        printf("Total table size %d\n",hc);
        printf("Total eq stat found %d\n",ec);
        printf("Total neq stat found %d\n",nec);
#if 0
        for(i=0;i<BITS;i++){
                long long r=nghb;
                printf("%d set={ ",i);
                for(j=0;j<BITS;j++){
                        if(!TEST_BIT(r,j)){
                                long long newneighb=r;
                                newneighb|=nghb;
                                int u=query_hash_entry(htable,newneighb);
                                if(htable==newneighb){
                                        printf("%d ",j);
                                }
                        }
                }
                printf("}\n");
        }
#endif
        return 0;
}

mathe 发表于 2009-10-16 09:23:20

发现宏STABLE已经不能再小了(除非修改代码再考虑对称性),实际上最后使用的数目为31816105.

〇〇 发表于 2009-10-16 14:33:33

如果在vc6下,将所有long long 改为__int64.
mathe 发表于 2009-10-16 09:17 http://bbs.emath.ac.cn/images/common/back.gif
我照做了,但是LL还报错,于是1LL->(__int64)1,0LL->(__int64)0
C:\vc6>cl ch.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
Copyright (C) Microsoft Corp 1984-1998. All rights reserved.

ch.cpp
Microsoft (R) Incremental Linker Version 6.00.8168
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

/out:ch.exe
ch.obj
ch.exe : warning LNK4084: total image size 800043008 exceeds max (268435456); image may not run

mathe 发表于 2009-10-16 15:03:57

你可以试着将htable的内存初始化改成动态分配(用malloc)

〇〇 发表于 2009-10-16 20:18:53

堆栈溢出?

〇〇 发表于 2009-10-16 20:29:29

不是说运行很长时间?
我把21楼改成下面,马上运行结束。
First fail
Total table size 0
Total eq stat found 0
Total neq stat found 0
// chp.cpp : Defines the entry point for the console application.
//

//#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#define N 8
#define BITS (N*N)
typedef unsigned __int64 SET;
SET nghb;
#define EMPTY_SET    (__int64)0
#define INDEX(x,y)   ((x)*N+(y))
#define GET_X(ind)   ((ind)/N)
#define GET_Y(ind)   ((ind)%N)
#define ADD_INDEX(s, ind)((s)|=(__int64)1<<(ind))
#define TEST_INDEX(s, ind)(((s)&((__int64)1<<(ind)))!=0)
#define CORNMASK   (3|(3<<N))
#define TEST_BIT(x, b)   (((x)&((__int64)1<<(b)))!=0)
#define SET_BIT(x, b)    ((x)|=((__int64)1<<(b)))

#define GET_CORN(x)(((x)&3)| (((x)>>N)&3)<<2)
#define DISP_CORN(x) (((x)&3)| ((((x)>>2)&3)<<N))
#define ECVALUE(x)   (((x)&~CORNMASK)|DISP_CORN(cr))

#define STABLE 50000033
#define WALK   1000
int hc;
int ec;
int nec;
int lec;
__int64 *htable=(__int64 *)malloc(sizeof(__int64)*STABLE);
//__int64 htable2;
char cr={1,-1,-1,-1,-1,-1,-1,-1,4,-1,5,-1,3,-1,11,7};
char rc={-1,0,-1,12,8,10,-1,15,-1,-1,-1,14,-1,-1,-1,-1};

FILE *fout;
void dump(__int64 v)
{
      int i,j;
      for(i=0;i<N;i++){
                for(j=0;j<N;j++){
                        if(TEST_BIT(v,i*N+j)){
                              fprintf(fout,"1 ");
                        }else{
                              fprintf(fout,"0 ");
                        }
                }
                fprintf(fout,"\n");
      }
      fprintf(fout,"\n");
}

void copy_ec(__int64 *p)
{
      int i,t;
      for(i=0,t=0;i<STABLE;i++){
                if(htable!=-(__int64)1){
                        if(cr)]!=-1){
                              p=htable;
                        }
                }
      }
}

void dump_ec(__int64 htable[])
{
      int i;
      fout = fopen("dump.txt","w");
      for(i=0;i<STABLE;i++){
                if(htable!=-(__int64)1){
                        if(cr)]!=-1){
                              dump(htable);
                        }
                }
      }
      fclose(fout);
}

void init()
{
    memset(htable,-1,sizeof(htable));
//      memset(htable2,-1,sizeof(htable2));
}

int hash(SET s)
{
    return (int)(s%STABLE);
}

int add_hash(__int64 htable[],__int64 key, bool eq)
{
    int v=hash(key);
    __int64 ev;
    ev=ECVALUE(key);
    if(hc>=STABLE){
      fprintf(stderr,"out of hash table range\n");
      exit(-1);
    }
    do{
      if(htable==-(__int64)1){
            if(eq){
                htable=ev;nec++;
            }else{
                htable=key;
                              ec++;
            }
            hc++;
            return v;
      }else if(htable!=key&&htable!=ev){
            v=(v+WALK)%STABLE;
      }else{
            if(eq){
                assert(htable==ev);
            }else{
                assert(htable==key);
            }
            return v;
      }
    }while(1);
}

int query_hash_entry(__int64 htable[],__int64 key)///return index to hash table
{
    __int64 ev=ECVALUE(key);
    int v=hash(key);
    do{
      if(htable==-(__int64)1)return v;
      if(htable==key||htable==ev)
            return v;
      v=(v+WALK)%STABLE;
    }while(1);
}

void init_neighbour()
{
    int i,j;
    for(i=0;i<N;i++){
      for(j=0;j<N;j++){
            SET s=EMPTY_SET;
            ADD_INDEX(s,INDEX(i,j));
            if(i>0&&j>0){
                ADD_INDEX(s,INDEX(i-1,j-1));
            }
            if(i>0){
                ADD_INDEX(s,INDEX(i-1,j));
            }
            if(j>0){
                ADD_INDEX(s,INDEX(i,j-1));
            }
            if(i>0&&j<N-1){
                ADD_INDEX(s,INDEX(i-1,j+1));
            }
            if(j<N-1){
                ADD_INDEX(s,INDEX(i,j+1));
            }
            if(i<N-1&&j>0){
                ADD_INDEX(s,INDEX(i+1,j-1));
            }
            if(i<N-1){
                ADD_INDEX(s,INDEX(i+1,j));
            }
            if(i<N-1&&j<N-1){
                ADD_INDEX(s,INDEX(i+1,j+1));
            }
            nghb=s;
      }
    }
}
#if 0
void visit(__int64 neighb)
{
      int i;
      int e=query_hash_entry(htable,neighb);
      if(htable==neighb){
                int ee=query_hash_entry(htable2,neighb);
                if(htable2==-1){
                        htable2=neighb;
                        lec++;
                        for(i=0;i<BITS;i++){
                              if(TEST_BIT(neighb,i)==0){
                                        __int64 newneighb=neighb;
                                        newneighb|=nghb;
                                        visit(newneighb);
                              }
                        }
                }
      }else{
                for(i=0;i<BITS;i++){
                        if(TEST_BIT(neighb,i)==0){
                              __int64 newneighb=neighb;
                              newneighb|=nghb;
                              int e2=query_hash_entry(htable,newneighb);
                              if(htable==newneighb){
                                        visit(newneighb);
                                        break;
                              }
                        }
                }
      }
}
#endif
int query(__int64 neighb)
{
    int e=query_hash_entry(htable,neighb);
    if(htable!=-1)
      return e;
    int i;
    for(i=0;i<BITS;i++){
      if(TEST_BIT(neighb,i)==0){
            __int64 newneighb=neighb;
            newneighb|=nghb;
            int r=query(newneighb);
            if(htable==newneighb)
                break;
      }
    }
    if(i<BITS){///find any status is newneighb
      return add_hash(htable,neighb,true);
    }else{
      return add_hash(htable,neighb,false);
    }
}

int cmpll(const void *p,const void *q)
{
      const __int64 *lp=(const __int64 *)p;
      const __int64 *lq=(const __int64 *)q;
      if(*lp==*lq)return 0;
      if(*lp<*lq)return -1;
      return 1;
}

int main(int argc, char* argv[])
{
      int i,j;
    init();
    init_neighbour();
    int s=query((__int64)0);
    if(htable==(__int64)0){
      printf("First fail\n");
    }else{
      printf("First successful\n");
    }
      printf("Total table size %d\n",hc);
      printf("Total eq stat found %d\n",ec);
      printf("Total neq stat found %d\n",nec);
#if 0
      for(i=0;i<BITS;i++){
                __int64 r=nghb;
                printf("%d set={ ",i);
                for(j=0;j<BITS;j++){
                        if(!TEST_BIT(r,j)){
                              __int64 newneighb=r;
                              newneighb|=nghb;
                              int u=query_hash_entry(htable,newneighb);
                              if(htable==newneighb){
                                        printf("%d ",j);
                              }
                        }
                }
                printf("}\n");
      }
#endif
      return 0;
}

mathe 发表于 2009-10-16 21:25:29


void init()

{

    memset(htable,-1,sizeof(htable));

//      memset(htable2,-1,sizeof(htable2));

}

需要修改

〇〇 发表于 2009-10-21 09:08:06

下载了一个Microsoft Visual C++ Toolkit 2003,可以编译long long了,运行时间确实很长

〇〇 发表于 2009-10-21 09:21:02

First fail
Total table size 31816105
Total eq stat found 5732950
Total neq stat found 26083155
Total lec stat found 1869201

〇〇 发表于 2009-10-21 14:32:19

21楼
Timer 3.01Copyright (c) 2002-2003 Igor Pavlov2003-07-10
First fail
Total table size 31816105
Total eq stat found 5732950
Total neq stat found 26083155

Kernel Time=   0.639 = 00:00:00.639 =   1%
User Time    =    45.240 = 00:00:45.240 =98%
Process Time =    45.879 = 00:00:45.879 =99%
Global Time=    45.911 = 00:00:45.911 = 100%
页: 1 2 [3] 4
查看完整版本: 一种棋类游戏