/**************************************************************************/ /* N-Queens Solutions ver3.1 takaken MAY/2003 */ /**************************************************************************/ #include #include #define MAXSIZE 24 #define MINSIZE 2 int SIZE, SIZEE; int BOARD[MAXSIZE], *BOARDE, *BOARD1, *BOARD2; int MASK, TOPBIT, SIDEMASK, LASTMASK, ENDBIT; int BOUND1, BOUND2; __int64 COUNT8, COUNT4, COUNT2; __int64 TOTAL, UNIQUE; /**********************************************/ /* 解答図の表示 */ /**********************************************/ void Display(void) { int y, bit; printf("N= %d\n", SIZE); for (y=0; y>=1) printf("%s ", (BOARD[y] & bit)? "Q": "-"); printf("\n"); } printf("\n"); } /**********************************************/ /* ユニーク解の判定とユニーク解の種類の判定 */ /**********************************************/ void Check(void) { int *own, *you, bit, ptn; /* 90度回転 */ if (*BOARD2 == 1) { for (ptn=2,own=BOARD+1; own<=BOARDE; own++,ptn<<=1) { bit = 1; for (you=BOARDE; *you!=ptn && *own>=bit; you--) bit <<= 1; if (*own > bit) return; if (*own < bit) break; } /* 90度回転して同型なら180度回転も270度回転も同型である */ if (own > BOARDE) { COUNT2++; //Display(); return; } } /* 180度回転 */ if (*BOARDE == ENDBIT) { for (you=BOARDE-1,own=BOARD+1; own<=BOARDE; own++,you--) { bit = 1; for (ptn=TOPBIT; ptn!=*you && *own>=bit; ptn>>=1) bit <<= 1; if (*own > bit) return; if (*own < bit) break; } /* 90度回転が同型でなくても180度回転が同型であることもある */ if (own > BOARDE) { COUNT4++; //Display(); return; } } /* 270度回転 */ if (*BOARD1 == TOPBIT) { for (ptn=TOPBIT>>1,own=BOARD+1; own<=BOARDE; own++,ptn>>=1) { bit = 1; for (you=BOARD; *you!=ptn && *own>=bit; you++) bit <<= 1; if (*own > bit) return; if (*own < bit) break; } } COUNT8++; //Display(); } /**********************************************/ /* 最上段行のクイーンが角以外にある場合の探索 */ /**********************************************/ void Backtrack2(int y, int left, int down, int right) { int bitmap, bit; bitmap = MASK & ~(left | down | right); if (y == SIZEE) { if (bitmap) { if (!(bitmap & LASTMASK)) { /* 最下段枝刈り */ BOARD[y] = bitmap; Check(); } } } else { if (y < BOUND1) { /* 上部サイド枝刈り */ bitmap |= SIDEMASK; bitmap ^= SIDEMASK; } else if (y == BOUND2) { /* 下部サイド枝刈り */ if (!(down & SIDEMASK)) return; if ((down & SIDEMASK) != SIDEMASK) bitmap &= SIDEMASK; } while (bitmap) { bitmap ^= BOARD[y] = bit = -bitmap & bitmap; Backtrack2(y+1, (left | bit)<<1, down | bit, (right | bit)>>1); } } } /**********************************************/ /* 最上段行のクイーンが角にある場合の探索 */ /**********************************************/ void Backtrack1(int y, int left, int down, int right) { int bitmap, bit; bitmap = MASK & ~(left | down | right); if (y == SIZEE) { if (bitmap) { BOARD[y] = bitmap; COUNT8++; //Display(); } } else { if (y < BOUND1) { /* 斜軸反転解の排除 */ bitmap |= 2; bitmap ^= 2; } while (bitmap) { bitmap ^= BOARD[y] = bit = -bitmap & bitmap; Backtrack1(y+1, (left | bit)<<1, down | bit, (right | bit)>>1); } } } /**********************************************/ /* 初期化と最上段行における探索の切り分け */ /**********************************************/ void NQueens(void) { int bit; /* Initialize */ COUNT8 = COUNT4 = COUNT2 = 0; SIZEE = SIZE - 1; BOARDE = &BOARD[SIZEE]; TOPBIT = 1 << SIZEE; MASK = (1 << SIZE) - 1; /* 0行目:000000001(固定) */ /* 1行目:011111100(選択) */ BOARD[0] = 1; for (BOUND1=2; BOUND1>1); } /* 0行目:000001110(選択) */ SIDEMASK = LASTMASK = TOPBIT | 1; ENDBIT = TOPBIT >> 1; for (BOUND1=1,BOUND2=SIZE-2; BOUND1>1); LASTMASK |= LASTMASK>>1 | LASTMASK<<1; ENDBIT >>= 1; } /* Unique and Total Solutions */ UNIQUE = COUNT8 + COUNT4 + COUNT2; TOTAL = COUNT8 * 8 + COUNT4 * 4 + COUNT2 * 2; } /**********************************************/ /* 探索時間文字列編集 */ /**********************************************/ void TimeFormat(clock_t utime, char *form) { int dd, hh, mm; float ftime, ss; ftime = (float)utime / CLOCKS_PER_SEC; mm = (int)ftime / 60; ss = ftime - (float)(mm * 60); dd = mm / (24 * 60); mm = mm % (24 * 60); hh = mm / 60; mm = mm % 60; if (dd) sprintf(form, "%4d %02d:%02d:%05.2f", dd, hh, mm, ss); else if (hh) sprintf(form, " %2d:%02d:%05.2f", hh, mm, ss); else if (mm) sprintf(form, " %2d:%05.2f", mm, ss); else sprintf(form, " %5.2f", ss); } /**********************************************/ /* Nクイーン問題 主制御部 */ /**********************************************/ int main(void) { clock_t starttime; char form[20]; printf("<------ N-Queens Solutions -----> <---- time ---->\n"); printf(" N: Total Unique days hh:mm:ss.--\n"); for (SIZE=MINSIZE; SIZE<=MAXSIZE; SIZE++) { starttime = clock(); NQueens(); TimeFormat(clock() - starttime, form); printf("%2d:%16I64d%16I64d %s\n", SIZE, TOTAL, UNIQUE, form); } return 0; }