- 注册时间
- 2007-12-27
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 40149
- 在线时间
- 小时
|
楼主 |
发表于 2008-6-6 15:30:25
|
显示全部楼层
上面的代码是如此的低效,以致于对于n=5的时候(这时空间复杂度还不是大问题,4维的rch数组现在的计算机还能够忍受),计算速度已经让人无法忍受了.
可以知道,实际计算过程计算机需要对于每个状态都调用一次上面的pass函数,而上面的pass函数实现过程使用了一个递归过程,显然里面会出现很多冗余的状态(很多状态会被多次遍历到,入对于"加一"操作两次分别添加到第1和第2个元素的操作,上面代码会两次遇到,分别是先加到第一个元素和先加到第二个元素.
为此,我对这个部分做了简单的优化,结果计算n=5就不是问题了:
思路很简单,我们先将所有的操作计算出来,保存在一个数组中,将重复的操作都剔除掉,然后实际使用过程分别试验使用这些预先保存的操作就可以提高很多效率了.
对于n=5的情况,我们可以将所有可能的操作进行编码,其中每个变换后的元素(4个元素)每一个都可以是变换前某个元素(5个选择,可以用3比特表示)通过0次(只能用于自身),1次,2次或3次"加一"操作得到(不同加法可以用2比特表示)
所以所有操作可以用最多4*(3+2)=20比特来表示
这部分代码同前面代码很像,它只是创建一个code数组-
- int ocount;
- #define MAX_OC 10000
- int code[MAX_OC];
- #define GET_OFFSET(x) ((x)&3)
- #define GET_TARGET(x) (((x)>>2)&3)
- #define CREATE_VALUE(offset,target) (((target)<<2)|(offset))
- void add(int x, int y, int z, int w)
- {
- int i;
- int u=TARGET(x,y,z,w);
- for(i=0;i<ocount;i++){
- if(code[i]==u)
- break;
- }
- if(i==ocount){
- code[ocount++]=u;
- }
- }
-
- #define enum_code_0(a,b,c,d) add(a,b,c,d)
- void enum_code_1(int x, int y, int z, int w)
- {
- int xu,yu,zu,wu;
- int xa,ya,za,wa;
- int xn,yn,zn,wn;
- add(x,y,z,w);
- xu=GET_TARGET(x);
- yu=GET_TARGET(y);
- zu=GET_TARGET(z);
- wu=GET_TARGET(w);
- xa=GET_OFFSET(x);
- ya=GET_OFFSET(y);
- za=GET_OFFSET(z);
- wa=GET_OFFSET(w);
- xn=CREATE_VALUE(xa+1,xu);
- yn=CREATE_VALUE(ya+1,yu);
- zn=CREATE_VALUE(za+1,zu);
- wn=CREATE_VALUE(wa+1,wu);
- enum_code_0(xn,y,z,w);
- enum_code_0(x,yn,z,w);
- enum_code_0(x,y,zn,w);
- enum_code_0(x,y,z,wn);
- enum_code_0(x,xn,z,w);
- enum_code_0(x,y,xn,w);
- enum_code_0(x,y,z,xn);
- enum_code_0(yn,y,z,w);
- enum_code_0(x,y,yn,w);
- enum_code_0(x,y,z,yn);
- enum_code_0(zn,y,z,w);
- enum_code_0(x,zn,z,w);
- enum_code_0(x,y,z,zn);
- enum_code_0(wn,y,z,w);
- enum_code_0(x,wn,z,w);
- enum_code_0(x,y,wn,w);
- }
-
- void enum_code_2(int x, int y, int z, int w)
- {
- int xu,yu,zu,wu;
- int xa,ya,za,wa;
- int xn,yn,zn,wn;
- add(x,y,z,w);
- xu=GET_TARGET(x);
- yu=GET_TARGET(y);
- zu=GET_TARGET(z);
- wu=GET_TARGET(w);
- xa=GET_OFFSET(x);
- ya=GET_OFFSET(y);
- za=GET_OFFSET(z);
- wa=GET_OFFSET(w);
- xn=CREATE_VALUE(xa+1,xu);
- yn=CREATE_VALUE(ya+1,yu);
- zn=CREATE_VALUE(za+1,zu);
- wn=CREATE_VALUE(wa+1,wu);
- enum_code_1(xn,y,z,w);
- enum_code_1(x,yn,z,w);
- enum_code_1(x,y,zn,w);
- enum_code_1(x,y,z,wn);
- enum_code_1(x,xn,z,w);
- enum_code_1(x,y,xn,w);
- enum_code_1(x,y,z,xn);
- enum_code_1(yn,y,z,w);
- enum_code_1(x,y,yn,w);
- enum_code_1(x,y,z,yn);
- enum_code_1(zn,y,z,w);
- enum_code_1(x,zn,z,w);
- enum_code_1(x,y,z,zn);
- enum_code_1(wn,y,z,w);
- enum_code_1(x,wn,z,w);
- enum_code_1(x,y,wn,w);
- }
-
- void enum_code_3(int x, int y, int z, int w)
- {
- int xu,yu,zu,wu;
- int xa,ya,za,wa;
- int xn,yn,zn,wn;
- add(x,y,z,w);
- xu=GET_TARGET(x);
- yu=GET_TARGET(y);
- zu=GET_TARGET(z);
- wu=GET_TARGET(w);
- xa=GET_OFFSET(x);
- ya=GET_OFFSET(y);
- za=GET_OFFSET(z);
- wa=GET_OFFSET(w);
- xn=CREATE_VALUE(xa+1,xu);
- yn=CREATE_VALUE(ya+1,yu);
- zn=CREATE_VALUE(za+1,zu);
- wn=CREATE_VALUE(wa+1,wu);
- enum_code_2(xn,y,z,w);
- enum_code_2(x,yn,z,w);
- enum_code_2(x,y,zn,w);
- enum_code_2(x,y,z,wn);
- enum_code_2(x,xn,z,w);
- enum_code_2(x,y,xn,w);
- enum_code_2(x,y,z,xn);
- enum_code_2(yn,y,z,w);
- enum_code_2(x,y,yn,w);
- enum_code_2(x,y,z,yn);
- enum_code_2(zn,y,z,w);
- enum_code_2(x,zn,z,w);
- enum_code_2(x,y,z,zn);
- enum_code_2(wn,y,z,w);
- enum_code_2(x,wn,z,w);
- enum_code_2(x,y,wn,w);
- }
-
- void init()
- {
- memset(rch,-1,sizeof(rch));
- enum_code_3(CREATE_VALUE(0,0),CREATE_VALUE(0,1),CREATE_VALUE(0,2),CREATE_VALUE(0,3));
- printf("total ocount=%d\n",ocount);
- rch[0][0][0][0]=TARGET(0,0,0,0);
- }
复制代码 此后,n=5对应的pass函数可以修改为:-
- int test(int x[4], int t)
- {
- int i;
- int y[4];
- for(i=0;i<ocount;i++){
- int u=code[i];
- int xu,yu,zu,wu;
- int xa,ya,za,wa;
- int x1,x2,x3,x4;
- x1=(u>>24)&0xFF;
- x2=(u>>16)&0xFF;
- x3=(u>>8)&0xFF;
- x4=u&0xFF;
- xu=GET_TARGET(x1);
- xa=GET_OFFSET(x1);
- yu=GET_TARGET(x2);
- ya=GET_OFFSET(x2);
- zu=GET_TARGET(x3);
- za=GET_OFFSET(x3);
- wu=GET_TARGET(x4);
- wa=GET_OFFSET(x4);
- y[0]=x[xu]+xa;
- y[1]=x[yu]+ya;
- y[2]=x[zu]+za;
- y[3]=x[wu]+wa;
- if(y[0]>t||y[1]>t||y[2]>t||y[3]>t)
- continue;
- if(y[0]<t&&y[1]<t&&y[2]<t&&y[3]<t)
- continue;
- if(rch[y[0]][y[1]][y[2]][y[3]]>=0)
- break;
- }
- if(i<ocount)return i;
- else return -1;
- }
-
- int pass(int a,int b, int c, int d)
- {
- int x[4];
- int i;
- x[0]=a,x[1]=b,x[2]=c,x[3]=d;
- for(i=0;i<4;i++){
- if(x[i]==d)x[i]=0;
- }
- if(d==0)return 0;
- return test(x,d-1);
- }
复制代码 |
|