const int size=8,maxsol=1;
int map[size][size];
int dx[]={2,1,-1,-2,-2,-1,1,2};
int dy[]={1,2,2,1,-1,-2,-2,-1};
int step=0,stepmax=5,x00=4,y00=3,w[size*size+1];
int sol=0,fx[size*size+1],fy[size*size+1];
long int times=0, every=1000000;
int rstep[64][8],ro[8];
int repeat=0,cpumax=1;
/** good order
int ro0[]={ 2,3,4,5,6,7,0,1};
int ro0[]={ 6,7,0,1,2,3,4,5};
**/
int ro0[]={ 2,3,4,5,6,7,0,1};
time_t start,end; int dif=0, dif0=0;
int showresult() {
int x,y;
sol++;
for (int i=0; i<=step; i++) printf("=>%i",w[i]);
// printf ("\nStep %i (after %i solutions with stepmax=%i)\n",step,sol,stepmax);
printf (" -- Solution %i\n\n",sol);
for (x=0; x<size;x++) {
for (y=0; y<size;y++) { printf("%3i",map[x][y]);}
printf ("\n\n");
}
time(&end); dif = difftime (end,start); printf ("CPU: %4i sec === CPU for this order %3i sec",dif,dif-dif0);
if (sol>=maxsol) { printf(" -- Succeed after %i attempts\n",repeat); exit(0);}
printf ("\n\n");
}
int status() {
int x,y;
printf ("Step Print: ");
for (int i=0; i<=step; i++) printf("=>%i",w[i]);
printf ("\nStep %i (after %i solutions with stepmax=%i)\n",step,sol,stepmax);
for (x=0; x<size;x++) {
for (y=0; y<size;y++) { printf("%3i",map[x][y]);}
printf ("\n\n");
}
time(&end); dif = difftime (end,start); printf ("CPU: %i sec === CPU for this roder %i sec",dif,dif-dif0);
printf ("\n\n");
}
int available() {
int x,y, way, x1,y1,ava,extempid[size*size][8],pos[size*size],pext[size*size][8];
int exit[size*size],nept,minext;
int iept,ichk,ichk2,icon;
int *mpt; char i;
int none=0, ione,oneid[size*size];
int nsolo=0, soloid[size*size];
mpt = map[0];
// minext: This is the minimum number of expextid in which empty position is not going to accept an extra check
minext = 3; int npos=0;
if (step<15 || size*size-step-3 < minext || step>59) return 1;
ava=1; nept=0; int size0=0;
for (x=0; x<size; x++) {
for (y=0; y<size; y++) {
if (map[x][y]==-1) {
pos[nept]=x*size+y; exit[nept]=0;
//if (step>60||step>=stepmax-1) { printf("checking %i,%i for %i,%i in step %i .....\n",x,y,fx[step],fy[step],step);}
for (way=0; way<8; way++) {
x1 = x+dx[way]; y1 = y+dy[way];
if (x1<0 || x1>size-1) continue;
if (y1<0 || y1>size-1)continue;
if (map[x1][y1]==-1) {
pext[nept][exit[nept]]=y1+size*x1;
exit[nept]++;
}
}
nept++;
if (exit[nept-1]>0) continue; else return 0;
}
npos++;
}
}
// 整理鄰居關係 extempid 表示在空格iept的地ichkext個出口,是第ichkemp個空格
int uncheck[size*size], ichkemp,ichkext, theext;
for (iept=0; iept<nept; iept++) {
for ( ichkext=0; ichkext<exit[iept]; ichkext++) {
for (ichkemp=0; ichkemp<nept; ichkemp++) {
if (pos[ichkemp]==pext[iept][ichkext]) {
extempid[iept][ichkext]= ichkemp;
break;
}
}
}
//计数出口是1的空格
if (exit[iept] == 1) { oneid[none]=iept; none++; }
// 如果有超过2个空格只有1个出口,则跳过
if (none > 2) return 0;
}
// return 1;
// printf ("tracing %i---- ",times); status();
int extcom1;
for (iept=0; iept<nept; iept++) {
// if (uncheck[iept] > 0) continue;
/* 如果某個空格的出口比最小出口數多,那麼無需檢查*/
if (exit[iept]<=minext) {
/* 如果某個空格的出口的出口,比最小出口數多,那麼無需檢查,或者,出口的出口比较自己的出口多,要等到出口更多的空格检查*/
for (ichk=0; ichk<exit[iept]; ichk++) {
if (exit[extempid[iept][ichk]]>minext || exit[extempid[iept][ichk]] > exit[iept]) break;
}
/* 如果某個空格的出口的出口,比最小出口數少*/
if (ichk == exit[iept]) {
//尋找循環關係的死胡同
nsolo=0;
for (ichk2=0; ichk2<exit[iept]; ichk2++) {
// if (exit[extempid[iept][ichk2]]>extmax) extmax= exit[extempid[iept][ichk2]];
// 如果某空格有超过1个出口的出口为1,则跳过
if (exit[extempid[iept][ichk2]]==1) {soloid[nsolo]=ichk2,nsolo++;}
if (nsolo>1) return 0;
for (theext=0; theext<exit[extempid[iept][ichk2]]; ++theext) {
extcom1 = extempid[extempid[iept][ichk2]][theext];
if (extcom1==iept) {
continue;
}
for (icon=0; icon<exit[extempid[iept][icon]];icon++) {
if (extempid[iept][icon] != extempid[extempid[iept][ichk2]][theext]) break;
}
if (icon<exit[extempid[iept][icon]]) goto nocheck;
}
/*還有其他類型死胡同,暫不編程檢查*/
}
if (ichk2 < exit[iept]) continue;
return 0;
}
nocheck: continue;
}
}
return 1;
}
int skord() {
int i,j,k,rd,step;
int order0[size],order[size];
for (i=0; i<size; i++) {
order0[i]=i;
}
for (i=0;i<size-1;i++) {
rd = rand() % (size-i);
k=0;
for (j=0; j<size-i; j++) {
if (j==rd) {k++; ro[i]=order0[j];}
order[j]=order0[k++];
}
for (j=0; j<size-i-1; j++) {
order0[j]=order[j];
}
}
ro[i]=order0[0];
}
int move(int x0, int y0) {
int x,y,way;
time(&end); dif = difftime (end,start);
if (dif-dif0>cpumax) {
step--;
return step;
}
step++;
for (w[step]=0; w[step]<8; w[step]++) {
x=x0+dx[ro[w[step]]]; if (x>7 || x<0) continue;
y=y0+dy[ro[w[step]]]; if (y>7 || y<0) continue;
if (map[x][y] != -1) continue;
map[x][y]=step;
fx[step]=x;fy[step]=y;
int av=available();
if (av==1) {
if (step <size*size-1) {
move(x,y);
time(&end); dif = difftime (end,start);
if (dif-dif0>cpumax) {
step--;
return step;
}
} else showresult();
}
map[x][y]=-1;
}
if (step>stepmax) stepmax=step;
step--; times++; return step;
}
int main (int argc, char *argv[]) {
char *endptr;
if (argc > 1) cpumax = strtol(argv[1], &endptr, 10);
int x,y,x0,y0,i;
time(&start);
srand ( time(&start) );
//
while (sol<=maxsol+1) {
for (x=0; x<size; x++) for (y=0; y<size; y++) map[x][y]=-1;
skord();
for (i=0; i<size; i++) {
printf(" %i ",ro[i]);
}
printf (" -- %i for trial order cpumax:%i\n",++repeat,cpumax);