USACO 1.5 Checker Challenge

题目描述:n皇后问题,规模6-13,按顺序输出前三组解,再输出总解数。

前一段学了点DLX的皮毛,就用它做了做,谁知道前三组解得输出顺序老出错。于是就放弃了。

看了hint,就暴搜了一回,开了4个数组,记录行、列、'/','\',的放皇后的情况,根据对称性,搜一半就行了。

my code
   
     
/*
ID: superbi1
LANG: C
TASK: checker
*/
#include
< stdio.h >
#include
< string .h >
#include
< stdlib.h >
#include
< time.h >
#define NL 15

int fr[NL][ 2 ], fc[NL][ 2 ], d1[NL * 2 ][ 2 ], d2[NL * 2 ][ 2 ];
int col[NL];
int n, cnt, re, flg;
FILE
* fout;

void DFS( int r)
{
int I;

if (r == n + 1 ) {
if (n > 6 && col[ 1 ] > (n + 1 ) / 2 ) { flg = 0 ; return ; }
if (cnt < 3 ) {
for (I = 1 ; I <= n; I ++ ) {
if (I > 1 ) fprintf(fout, " " );
fprintf(fout,
" %d " , col[I]);
}
fprintf(fout,
" \n " );
}
if (n & 1 && col[ 1 ] == (n + 1 ) / 2 ) re ++ ;
cnt
++ ;
return ;
}
for (I = 1 ; I <= n; I ++ ) {
if ( ! flg) return ;
if ( ! fr[r][ 1 ] && ! fc[I][ 1 ] && ! d1[r - I + n][ 1 ] && ! d2[r + I][ 1 ]) {
fr[r][
1 ] = 1 ;
fc[I][
1 ] = 1 ;
d1[r
- I + n][ 1 ] = 1 ;
d2[r
+ I][ 1 ] = 1 ;
fr[r][
0 ] ++ ;
fc[I][
0 ] ++ ;
d1[r
- I + n][ 0 ] ++ ;
d2[r
+ I][ 0 ] ++ ;

col[r]
= I;
DFS(r
+ 1 );

fr[r][
0 ] -- ;
fc[I][
0 ] -- ;
d1[r
- I + n][ 0 ] -- ;
d2[r
+ I][ 0 ] -- ;
if (fr[r][ 0 ] == 0 ) fr[r][ 1 ] = 0 ;
if (fc[I][ 0 ] == 0 ) fc[I][ 1 ] = 0 ;
if (d1[r - I + n][ 0 ] == 0 ) d1[r - I + n][ 1 ] = 0 ;
if (d2[r + I][ 0 ] == 0 ) d2[r + I][ 1 ] = 0 ;
}
}
}

int main()
{
int time = clock();
FILE
* fin = fopen( " checker.in " , " r " );
fout
= fopen( " checker.out " , " w " );
fscanf(fin,
" %d " , & n);
memset(fr,
0 , sizeof (fr));
memset(fc,
0 , sizeof (fc));
memset(d1,
0 , sizeof (d1));
memset(d2,
0 , sizeof (d2));
cnt
= 0 ;
re
= 0 ;
flg
= 1 ;
DFS(
1 );
if (n == 6 ) cnt = 2 ;
fprintf(fout,
" %d\n " , (cnt - re) * 2 + re);
printf(
" %dms\n " , clock() - time);
return 0 ;
}

 

看了解题报告,发现自己写的好烂,首先,不需要记录行(why?),其次,直接记录个数,标记是多余的。

standard
   
     
1 /*
2 TASK: checker
3 LANG: C
4   */
5 #include < stdio.h >
6 #include < stdlib.h >
7 #include < string .h >
8 #include < assert.h >
9
10   #define MAXN 16
11
12   int n;
13 int nsol, nprinted;
14 char row[MAXN];
15 FILE * fout;
16
17 void
18 solution() {
19 int i;
20 for (i = 0 ; i < n; i ++ ) {
21 if (i != 0 ) fprintf(fout, " " );
22 fprintf(fout, " %d " , row[i] + 1 );
23 }
24 fprintf(fout, " \n " );
25 }
26
27 /* Keep track of whether there is a checker on each column, and diagonal. */
28 char col[MAXN]; /* (i, j) -> j */
29 char updiag[ 2 * MAXN]; /* (i, j) -> i+j */
30 char downdiag[ 2 * MAXN]; /* (i, j) -> i-j + N */
31
32 /*
33 * Calculate number of ways to place checkers
34 * on each row of the board starting at row i and going to row n.
35 */
36 void
37 nway(i, lim) {
38 int j;
39
40 if (i == n) {
41 nsol ++ ;
42 if (n > 6 && row[ 0 ] < n / 2 ) nsol ++ ;
43 if (nprinted ++ < 3 ) solution();
44 return ;
45 }
46
47 for (j = 0 ; j < lim; j ++ ){
48 if ( ! col[j] && ! updiag[i + j] && ! downdiag[i - j + MAXN]){
49 row[i] = j;
50
51 col[j] ++ ;
52 updiag[i + j] ++ ;
53 downdiag[i - j + MAXN] ++ ;
54
55 nway(i + 1 ,n);
56
57 col[j] -- ;
58 updiag[i + j] -- ;
59 downdiag[i - j + MAXN] -- ;
60 }
61 }
62 }
63
64 main( void ) {
65 FILE * fin = fopen( " checker.in " , " r " );
66 fout = fopen( " checker.out " , " w " );
67 fscanf(fin, " %d " , & n);
68 nway( 0 , n > 6 ? (n + 1 ) / 2 :n);
69 fprintf(fout, " %d\n " , nsol);
70 exit ( 0 );
71 }
72
73

 

这个更牛,用的位标记+栈模拟的递归,有空再研究吧~

牛叉
   
     
1 #include < stdio.h >
2 #include < stdlib.h >
3 #include < fstream.h >
4 #define MAX_BOARDSIZE 16
5 typedef unsigned long SOLUTIONTYPE;
6 #define MIN_BOARDSIZE 6
7 SOLUTIONTYPE g_numsolutions = 0 ;
8
9 void Nqueen( int board_size) {
10 int aQueenBitRes[MAX_BOARDSIZE]; /* results */
11 int aQueenBitCol[MAX_BOARDSIZE]; /* marks used columns */
12 int aQueenBitPosDiag[MAX_BOARDSIZE]; /* marks used "positive diagonals" */
13 int aQueenBitNegDiag[MAX_BOARDSIZE]; /* marks used "negative diagonals" */
14 int aStack[MAX_BOARDSIZE + 2 ]; /* a stack instead of recursion */
15 int * pnStack;
16
17 int numrows = 0 ; /* numrows redundant - could use stack */
18 unsigned int lsb; /* least significant bit */
19 unsigned int bitfield; /* set bits denote possible queen positions */
20 int i;
21 int odd = board_size & 1 ; /* 1 if board_size odd */
22 int board_m1 = board_size - 1 ; /* board size - 1 */
23 int mask = ( 1 << board_size) - 1 ; /* N bit mask of all 1's */
24
25 aStack[ 0 ] = - 1 ; /* sentinel signifies end of stack */
26 for (i = 0 ; i < ( 1 + odd); ++ i) {
27 bitfield = 0 ;
28 if ( 0 == i) {
29 int half = board_size >> 1 ; /* divide by two */
30 bitfield = ( 1 << half) - 1 ;
31 pnStack = aStack + 1 ; /* stack pointer */
32 aQueenBitRes[ 0 ] = 0 ;
33 aQueenBitCol[ 0 ] = aQueenBitPosDiag[ 0 ] = aQueenBitNegDiag[ 0 ] = 0 ;
34 } else {
35 bitfield = 1 << (board_size >> 1 );
36 numrows = 1 ; /* prob. already 0 */
37
38 aQueenBitRes[ 0 ] = bitfield;
39 aQueenBitCol[ 0 ] = aQueenBitPosDiag[ 0 ] = aQueenBitNegDiag[ 0 ] = 0 ;
40 aQueenBitCol[ 1 ] = bitfield;
41
42 aQueenBitNegDiag[ 1 ] = (bitfield >> 1 );
43 aQueenBitPosDiag[ 1 ] = (bitfield << 1 );
44 pnStack = aStack + 1 ; /* stack pointer */
45 * pnStack ++ = 0 ; /* row done -- only 1 element & we've done it */
46 bitfield = (bitfield - 1 ) >> 1 ;
47 /* bitfield -1 is all 1's to the left of the single 1 */
48 }
49 for (;;) {
50 lsb = - ((signed)bitfield) & bitfield;
51 /* this assumes a 2's complement architecture */
52 if ( 0 == bitfield) {
53 bitfield = *-- pnStack; /* get prev. bitfield from stack */
54 if (pnStack == aStack) /* if sentinel hit.... */
55 break ;
56 -- numrows;
57 continue ;
58 }
59 bitfield &= ~ lsb; /* bit off -> don't try it again */
60 aQueenBitRes[numrows] = lsb; /* save the result */
61 if (numrows < board_m1) { /* more rows to process? */
62 int n = numrows ++ ;
63 aQueenBitCol[numrows] = aQueenBitCol[n] | lsb;
64 aQueenBitNegDiag[numrows] = (aQueenBitNegDiag[n] | lsb) >> 1 ;
65 aQueenBitPosDiag[numrows] = (aQueenBitPosDiag[n] | lsb) << 1 ;
66 * pnStack ++ = bitfield;
67 bitfield = mask & ~ (aQueenBitCol[numrows] |
68 aQueenBitNegDiag[numrows] | aQueenBitPosDiag[numrows]);
69 continue ;
70 } else {
71 ++ g_numsolutions;
72 bitfield = *-- pnStack;
73 -- numrows;
74 continue ;
75 }
76 }
77 }
78 g_numsolutions *= 2 ;
79 }
80
81 int main( int argc, char ** argv) {
82 ifstream f( " checker.in " );
83 ofstream g( " checker.out " );
84 long boardsize,s[ 20 ],ok,k,i,sol = 0 ;
85 f >> boardsize;
86 Nqueen (boardsize);
87 k = 1 ;
88 s[k] = 0 ;
89 while (k > 0 ) {
90 ok = 0 ;
91 while (s[k] < boardsize && ! ok) {
92 ok = 1 ;
93 s[k] ++ ;
94 for (i = 1 ;i < k;i ++ )
95 if (s[i] == s[k] || abs(s[k] - s[i]) == abs(k - i))
96 ok = 0 ;
97 }
98 if (sol != 3 )
99 if ( ! ok)
100 k -- ;
101 else
102 if (k == boardsize) {
103 for (i = 1 ;i < boardsize;i ++ ) {
104 for ( int j = 1 ;j <= boardsize;j ++ )
105 if (s[i] == j) g << j << " " ;
106 }
107 for (i = 1 ;i <= boardsize;i ++ )
108 if (s[boardsize] == i) g << i;
109 g << " \n " ;
110 sol ++ ;
111 } else {
112 k ++ ;
113 s[k] = 0 ;
114 } else break ;
115 }
116 g << g_numsolutions << " \n " ;
117 f.close();
118 g.close();
119 return 0 ;
120 }
121
122

 

你可能感兴趣的:(USACO)