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

 

posted @ 2010-05-25 21:24  superbin  阅读(399)  评论(0编辑  收藏  举报