#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
struct node {
void *data;
struct node *left, *right;
};
void *push(struct node **root, void *data, int n, int (*cmp)(void *, void *, int n)) {
struct node *p;
int c;
if (!*root) {
if ((p
= malloc(sizeof(struct node
))) == 0) { fprintf(stderr
, "cannot allocate enough memory(struct node), aborted\n"); }
p->data = data;
p->left = p->right = 0;
*root = p;
return data;
}
if ((c = (*cmp)(data, (*root)->data, n)) != 0) {
if (c < 0) {
return push(&((*root)->left), data, n, cmp);
} else {
return push(&((*root)->right), data, n, cmp);
}
} else {
return (*root)->data;
}
}
void release(struct node **root) {
if (*root != 0) {
release(&((*root)->right));
release(&((*root)->left));
*root = 0;
}
}
void phase2image(int *phase, int **image, int n) {
int y, x;
for (y = 0; y < n; y++) for (x = 0; x < n; x++) image[y][x] = 0;
for (x = 0; x < n; x++)
image[phase[x]][x] = 1;
}
void image2phase(int **image, int *phase, int n) {
int x, y;
for (x = 0; x < n; x++)
for (y = 0; y < n; y++)
if (image[y][x] > 0)
phase[x] = y;
}
void rotate(int *phase, int n, int **work) {
int x, y;
phase2image(phase, work, n);
for (y = 0; y < n; y++)
for (x = 0; x < n; x++)
work[n - 1 - x][y + n] = work[y] [x];
for (y = 0; y < n; y++)
for (x = 0; x < n; x++)
work[y][x] = work[y][x + n];
image2phase(work, phase, n);
}
void mirror(int *phase, int n, int **work) {
int x, y;
phase2image(phase, work, n);
for (y = 0; y < n; y++)
for (x = 0; x < y; x++) {
int t;
t = work[y][x];
work[y][x] = work[x][y];
work[x][y] = t;
}
image2phase(work, phase, n);
}
int cmp(int *p, int *q, int n) {
int i, x;
for (i = n - 1; i >= 0 && !(x = p[i] - q[i]); i--)
;
return x;
}
int checkAndRegister(int *phase, int n, int **work, struct node **root) {
int *p;
int i;
if ((p
= malloc(sizeof(int) * n
)) != 0) { memcpy(p
, phase
, sizeof(int) * n
); if (push(root, p, n, (int (*)(void *, void *, int))cmp) != p) {
return 0;
}
for (i = 0; i < 3; i++) {
rotate(phase, n, work);
if ((p
= malloc(sizeof(int) * n
)) == 0) { goto bad_alloc;
}
memcpy(p
, phase
, sizeof(int) * n
); if (push(root, p, n, (int (*)(void *, void *, int))cmp) != p)
}
rotate(phase, n, work);
mirror(phase, n, work);
if ((p
= malloc(sizeof(int) * n
)) == 0) { goto bad_alloc;
}
memcpy(p
, phase
, sizeof(int) * n
); if (push(root, p, n, (int (*)(void *, void *, int))cmp) != p)
for (i = 0; i < 3; i++) {
rotate(phase, n, work);
if ((p
= malloc(sizeof(int) * n
)) == 0) { goto bad_alloc;
}
memcpy(p
, phase
, sizeof(int) * n
); if (push(root, p, n, (int (*)(void *, void *, int))cmp) != p)
}
} else {/* bad alloc */
bad_alloc:
fprintf(stderr
, "cannnot allocate enough memory, aborted.\n"); }
return 1;
}
static int counter1 = 0;
static int counter2 = 0;
void output_phase(int *d, int n, int **work) {
int x, y;
for (x = 0; x < n; x++)
for (y = 0; y < n; y++)
work[y][x] = 0;
for (x = 0; x < n; x++)
work[d[x]][x] = 1;
for (y = 0; y < n; y++) {
for (x = 0; x < n; x++)
if (work[y][x])
else
}
}
int noqueen(int *c, int x, int y, int n, int **work) { /* set y-pos for given x-pos */
int i, tx, ty;
if (x == 0)
return 1;
for (tx = 0; tx < n; tx++) /* clear work */
for (ty = 0; ty < n; ty++)
work[ty][tx] = 0;
for (i = 0; i < x; i++)
work[c[i]][i] = 1; /* set y-pos for given x-pos */
/* left-upper */
tx = x; ty = y;
while (tx >= 0 && ty >= 0) { tx--; ty--; }
tx++; ty++;
while (tx < x && ty < y) {
if (work[ty][tx])
return 0;
tx++; ty++;
}
/* left-downer */
tx = x; ty = y;
while (tx >= 0 && ty < n) { tx--; ty++; }
tx++; ty--;
while (tx < x && ty > y) {
if (work[ty][tx])
return 0;
tx++; ty--;
}
return 1;
}
void f(int p, int *a, int n, int **work, struct node **root) {
int i;
if (n == p) {
counter2++;
if (checkAndRegister(a + n, n, work, root)) {
++counter1;
/* printf("%d-%d\n", n, ++counter1); */
/* output_phase(a + n, n, work);*/
}
} else {
int *b;
if ((b
= malloc(sizeof(int) * n
* 2)) != 0) { for (i = 0; i < n; i++)
if (a[i] < 0) {
if (noqueen(a + n, p, i, n, work)) {
memcpy(b
, a
, sizeof(int) * n
* 2); b[i] = p;
b[n + p] = i;
f(p + 1, b, n, work, root);
}
}
}
}
}
int main(int argc, char *argv[]) {
int *a, n, i;
int **work;
struct node *root;
time_t t, t2;
for(n = 1; n <= 16; n++) {
/* allocate work area */
if ((work
= malloc(sizeof(int *) * n
)) != 0) { int k;
for (k = 0; k < n; k++) work[k] = 0;
for (k = 0; k < n; k++)
if ((work
[k
] = malloc(sizeof(int) * n
* 2)) == 0) break;
if (k == n) {
/* start actual calcaulationg */
if ((a
= malloc(sizeof(int) * n
* 2)) != 0) { for (i = 0; i < n; i++)
a[i] = -1;
counter1 = counter2 = 0;
root = 0;
f(0, a, n, work, &root);
printf("uniq: %d, all:%d, ", counter1
, counter2
); release(&root);
}
}
/* release work area */
for (k = 0; k < n; k++)
}
}
return 0;
}
/* end */
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8dGltZS5oPgoKc3RydWN0IG5vZGUgewogIHZvaWQgKmRhdGE7CiAgc3RydWN0IG5vZGUgKmxlZnQsICpyaWdodDsKfTsKCnZvaWQgKnB1c2goc3RydWN0IG5vZGUgKipyb290LCB2b2lkICpkYXRhLCBpbnQgbiwgaW50ICgqY21wKSh2b2lkICosIHZvaWQgKiwgaW50IG4pKSB7CiAgc3RydWN0IG5vZGUgKnA7CiAgaW50IGM7CiAgaWYgKCEqcm9vdCkgewogICAgaWYgKChwID0gbWFsbG9jKHNpemVvZihzdHJ1Y3Qgbm9kZSkpKSA9PSAwKSB7CiAgICAgIGZwcmludGYoc3RkZXJyLCAiY2Fubm90IGFsbG9jYXRlIGVub3VnaCBtZW1vcnkoc3RydWN0IG5vZGUpLCBhYm9ydGVkXG4iKTsKICAgICAgZXhpdCgtMSk7CiAgICB9CiAgICBwLT5kYXRhID0gZGF0YTsKICAgIHAtPmxlZnQgPSBwLT5yaWdodCA9IDA7CiAgICAqcm9vdCA9IHA7CiAgICByZXR1cm4gZGF0YTsKICB9IAogIGlmICgoYyA9ICgqY21wKShkYXRhLCAoKnJvb3QpLT5kYXRhLCBuKSkgIT0gMCkgewogICAgaWYgKGMgPCAwKSB7CiAgICAgIHJldHVybiBwdXNoKCYoKCpyb290KS0+bGVmdCksIGRhdGEsIG4sIGNtcCk7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gcHVzaCgmKCgqcm9vdCktPnJpZ2h0KSwgZGF0YSwgbiwgY21wKTsKICAgIH0KICB9IGVsc2UgewogICAgcmV0dXJuICgqcm9vdCktPmRhdGE7CiAgfQp9Cgp2b2lkIHJlbGVhc2Uoc3RydWN0IG5vZGUgKipyb290KSB7CiAgaWYgKCpyb290ICE9IDApIHsKICAgIHJlbGVhc2UoJigoKnJvb3QpLT5yaWdodCkpOwogICAgcmVsZWFzZSgmKCgqcm9vdCktPmxlZnQpKTsKICAgIGZyZWUoKCpyb290KS0+ZGF0YSk7CiAgICBmcmVlKCpyb290KTsKICAgICpyb290ID0gMDsKICB9Cn0KCnZvaWQgcGhhc2UyaW1hZ2UoaW50ICpwaGFzZSwgaW50ICoqaW1hZ2UsIGludCBuKSB7CiAgaW50IHksIHg7CiAgZm9yICh5ID0gMDsgeSA8IG47IHkrKykgZm9yICh4ID0gMDsgeCA8IG47IHgrKykgaW1hZ2VbeV1beF0gPSAwOwogIGZvciAoeCA9IDA7IHggPCBuOyB4KyspCiAgICBpbWFnZVtwaGFzZVt4XV1beF0gPSAxOwp9Cgp2b2lkIGltYWdlMnBoYXNlKGludCAqKmltYWdlLCBpbnQgKnBoYXNlLCBpbnQgbikgewogIGludCB4LCB5OwogIGZvciAoeCA9IDA7IHggPCBuOyB4KyspCiAgICBmb3IgKHkgPSAwOyB5IDwgbjsgeSsrKQogICAgICBpZiAoaW1hZ2VbeV1beF0gPiAwKQogICAgICAgIHBoYXNlW3hdID0geTsKfQoKdm9pZCByb3RhdGUoaW50ICpwaGFzZSwgaW50IG4sIGludCAqKndvcmspIHsKICBpbnQgeCwgeTsKICBwaGFzZTJpbWFnZShwaGFzZSwgd29yaywgbik7CiAgZm9yICh5ID0gMDsgeSA8IG47IHkrKykKICAgIGZvciAoeCA9IDA7IHggPCBuOyB4KyspCiAgICAgIHdvcmtbbiAtIDEgLSB4XVt5ICsgbl0gPSB3b3JrW3ldIFt4XTsKICBmb3IgKHkgPSAwOyB5IDwgbjsgeSsrKQogICAgZm9yICh4ID0gMDsgeCA8IG47IHgrKykKICAgICAgd29ya1t5XVt4XSA9IHdvcmtbeV1beCArIG5dOwogIGltYWdlMnBoYXNlKHdvcmssIHBoYXNlLCBuKTsKfQoKdm9pZCBtaXJyb3IoaW50ICpwaGFzZSwgaW50IG4sIGludCAqKndvcmspIHsKICBpbnQgeCwgeTsKICAKICBwaGFzZTJpbWFnZShwaGFzZSwgd29yaywgbik7CiAgZm9yICh5ID0gMDsgeSA8IG47IHkrKykKICAgIGZvciAoeCA9IDA7IHggPCB5OyB4KyspIHsKICAgICAgaW50IHQ7CiAgICAgIHQgPSB3b3JrW3ldW3hdOwogICAgICB3b3JrW3ldW3hdID0gd29ya1t4XVt5XTsKICAgICAgd29ya1t4XVt5XSA9IHQ7CiAgICB9CiAgaW1hZ2UycGhhc2Uod29yaywgcGhhc2UsIG4pOwp9CgppbnQgY21wKGludCAqcCwgaW50ICpxLCBpbnQgbikgewogIGludCBpLCB4OwogIGZvciAoaSA9IG4gLSAxOyBpID49IDAgJiYgISh4ID0gcFtpXSAtIHFbaV0pOyBpLS0pCiAgICA7CiAgcmV0dXJuIHg7Cn0KCmludCBjaGVja0FuZFJlZ2lzdGVyKGludCAqcGhhc2UsIGludCBuLCBpbnQgKip3b3JrLCBzdHJ1Y3Qgbm9kZSAqKnJvb3QpIHsKICBpbnQgKnA7CiAgaW50IGk7CiAgaWYgKChwID0gbWFsbG9jKHNpemVvZihpbnQpICogbikpICE9IDApIHsKICAgIG1lbWNweShwLCBwaGFzZSwgc2l6ZW9mKGludCkgKiBuKTsKICAgIGlmIChwdXNoKHJvb3QsIHAsIG4sIChpbnQgKCopKHZvaWQgKiwgdm9pZCAqLCBpbnQpKWNtcCkgIT0gcCkgewogICAgICBmcmVlKHApOwogICAgICByZXR1cm4gMDsKICAgIH0KCiAgICBmb3IgKGkgPSAwOyBpIDwgMzsgaSsrKSB7CiAgICAgIHJvdGF0ZShwaGFzZSwgbiwgd29yayk7CiAgICAgIGlmICgocCA9IG1hbGxvYyhzaXplb2YoaW50KSAqIG4pKSA9PSAwKSB7CiAgICAgICAgZ290byBiYWRfYWxsb2M7CiAgICAgIH0KICAgICAgbWVtY3B5KHAsIHBoYXNlLCBzaXplb2YoaW50KSAqIG4pOwogICAgICBpZiAocHVzaChyb290LCBwLCBuLCAoaW50ICgqKSh2b2lkICosIHZvaWQgKiwgaW50KSljbXApICE9IHApCiAgICAgICAgZnJlZShwKTsKICAgIH0KICAgIHJvdGF0ZShwaGFzZSwgbiwgd29yayk7CiAgICBtaXJyb3IocGhhc2UsIG4sIHdvcmspOwogICAgaWYgKChwID0gbWFsbG9jKHNpemVvZihpbnQpICogbikpID09IDApIHsKICAgICAgZ290byBiYWRfYWxsb2M7CiAgICB9CiAgICBtZW1jcHkocCwgcGhhc2UsIHNpemVvZihpbnQpICogbik7CiAgICBpZiAocHVzaChyb290LCBwLCBuLCAoaW50ICgqKSh2b2lkICosIHZvaWQgKiwgaW50KSljbXApICE9IHApCiAgICAgIGZyZWUocCk7CgogICAgZm9yIChpID0gMDsgaSA8IDM7IGkrKykgewogICAgICByb3RhdGUocGhhc2UsIG4sIHdvcmspOwogICAgICBpZiAoKHAgPSBtYWxsb2Moc2l6ZW9mKGludCkgKiBuKSkgPT0gMCkgewogICAgICAgIGdvdG8gYmFkX2FsbG9jOwogICAgICB9CiAgICAgIG1lbWNweShwLCBwaGFzZSwgc2l6ZW9mKGludCkgKiBuKTsKICAgICAgaWYgKHB1c2gocm9vdCwgcCwgbiwgKGludCAoKikodm9pZCAqLCB2b2lkICosIGludCkpY21wKSAhPSBwKQogICAgICAgIGZyZWUocCk7CiAgICB9CgogIH0gZWxzZSB7LyogYmFkIGFsbG9jICovCiAgYmFkX2FsbG9jOgogICAgZnByaW50ZihzdGRlcnIsICJjYW5ubm90IGFsbG9jYXRlIGVub3VnaCBtZW1vcnksIGFib3J0ZWQuXG4iKTsKICAgIGV4aXQoMSk7CiAgfQogIHJldHVybiAxOwp9CgpzdGF0aWMgaW50IGNvdW50ZXIxID0gMDsKc3RhdGljIGludCBjb3VudGVyMiA9IDA7Cgp2b2lkIG91dHB1dF9waGFzZShpbnQgKmQsIGludCBuLCBpbnQgKip3b3JrKSB7CiAgaW50IHgsIHk7CiAgZm9yICh4ID0gMDsgeCA8IG47IHgrKykKICAgIGZvciAoeSA9IDA7IHkgPCBuOyB5KyspCiAgICAgIHdvcmtbeV1beF0gPSAwOwogIGZvciAoeCA9IDA7IHggPCBuOyB4KyspCiAgICB3b3JrW2RbeF1dW3hdID0gMTsKICBmb3IgKHkgPSAwOyB5IDwgbjsgeSsrKSB7CiAgICBmb3IgKHggPSAwOyB4IDwgbjsgeCsrKQogICAgICBpZiAod29ya1t5XVt4XSkKICAgICAgICBwdXRjaGFyKCdRJyk7CiAgICAgIGVsc2UKICAgICAgICBwdXRjaGFyKCcuJyk7CiAgICBwdXRjaGFyKCdcbicpOwogIH0KICBwdXRjaGFyKCdcbicpOwp9CgppbnQgbm9xdWVlbihpbnQgKmMsIGludCB4LCBpbnQgeSwgaW50IG4sIGludCAqKndvcmspIHsgLyogc2V0IHktcG9zIGZvciBnaXZlbiB4LXBvcyAqLwogIGludCBpLCB0eCwgdHk7CiAgaWYgKHggPT0gMCkKICAgIHJldHVybiAxOwogIGZvciAodHggPSAwOyB0eCA8IG47IHR4KyspIC8qIGNsZWFyIHdvcmsgKi8KICAgIGZvciAodHkgPSAwOyB0eSA8IG47IHR5KyspCiAgICAgIHdvcmtbdHldW3R4XSA9IDA7CiAgZm9yIChpID0gMDsgaSA8IHg7IGkrKykKICAgIHdvcmtbY1tpXV1baV0gPSAxOyAgLyogc2V0IHktcG9zIGZvciBnaXZlbiB4LXBvcyAqLwogIC8qIGxlZnQtdXBwZXIgKi8KICB0eCA9IHg7IHR5ID0geTsKICB3aGlsZSAodHggPj0gMCAmJiB0eSA+PSAwKSB7IHR4LS07IHR5LS07IH0KICB0eCsrOyB0eSsrOwogIHdoaWxlICh0eCA8IHggJiYgdHkgPCB5KSB7CiAgICBpZiAod29ya1t0eV1bdHhdKQogICAgICByZXR1cm4gMDsKICAgIHR4Kys7IHR5Kys7CiAgfQogIC8qIGxlZnQtZG93bmVyICovCiAgdHggPSB4OyB0eSA9IHk7CiAgd2hpbGUgKHR4ID49IDAgJiYgdHkgPCBuKSB7IHR4LS07IHR5Kys7IH0KICB0eCsrOyB0eS0tOwogIHdoaWxlICh0eCA8IHggJiYgdHkgPiB5KSB7CiAgICBpZiAod29ya1t0eV1bdHhdKQogICAgICByZXR1cm4gMDsKICAgIHR4Kys7IHR5LS07CiAgfQogIHJldHVybiAxOwp9Cgp2b2lkIGYoaW50IHAsIGludCAqYSwgaW50IG4sIGludCAqKndvcmssIHN0cnVjdCBub2RlICoqcm9vdCkgewogIGludCBpOwogIGlmIChuID09IHApIHsKICAgIGNvdW50ZXIyKys7CiAgICBpZiAoY2hlY2tBbmRSZWdpc3RlcihhICsgbiwgbiwgd29yaywgcm9vdCkpIHsKICAgICAgKytjb3VudGVyMTsKLyogICAgICBwcmludGYoIiVkLSVkXG4iLCBuLCArK2NvdW50ZXIxKTsgKi8KLyogICAgICBvdXRwdXRfcGhhc2UoYSArIG4sIG4sIHdvcmspOyovCiAgICB9CiAgfSBlbHNlIHsKICAgIGludCAqYjsKICAgIGlmICgoYiA9IG1hbGxvYyhzaXplb2YoaW50KSAqIG4gKiAyKSkgIT0gMCkgewogICAgICBmb3IgKGkgPSAwOyBpIDwgbjsgaSsrKQogICAgICAgIGlmIChhW2ldIDwgMCkgewogICAgICAgICAgaWYgKG5vcXVlZW4oYSArIG4sIHAsIGksIG4sIHdvcmspKSB7CiAgICAgICAgICAgIG1lbWNweShiLCBhLCBzaXplb2YoaW50KSAqIG4gKiAyKTsKICAgICAgICAgICAgYltpXSA9IHA7CiAgICAgICAgICAgIGJbbiArIHBdID0gaTsKICAgICAgICAgICAgZihwICsgMSwgYiwgbiwgd29yaywgcm9vdCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICBmcmVlKGIpOwogICAgfQogIH0KfQoKaW50IG1haW4oaW50IGFyZ2MsIGNoYXIgKmFyZ3ZbXSkgewogIGludCAqYSwgbiwgaTsKICBpbnQgKip3b3JrOwogIHN0cnVjdCBub2RlICpyb290OwogIHRpbWVfdCB0LCB0MjsKCiAgZm9yKG4gPSAxOyBuIDw9IDE2OyBuKyspIHsKICAgIC8qIGFsbG9jYXRlIHdvcmsgYXJlYSAqLwogICAgdGltZSgmdCk7CiAgICBwcmludGYoIm46ICVkLCAiLCBuKTsKICAgIGlmICgod29yayA9IG1hbGxvYyhzaXplb2YoaW50ICopICogbikpICE9IDApIHsKICAgICAgaW50IGs7CiAgICAgIGZvciAoayA9IDA7IGsgPCBuOyBrKyspIHdvcmtba10gPSAwOwogICAgICBmb3IgKGsgPSAwOyBrIDwgbjsgaysrKQogICAgICAgIGlmICgod29ya1trXSA9IG1hbGxvYyhzaXplb2YoaW50KSAqIG4gKiAyKSkgPT0gMCkKICAgICAgICAgIGJyZWFrOwogICAgICBpZiAoayA9PSBuKSB7CgogICAgICAvKiBzdGFydCBhY3R1YWwgY2FsY2F1bGF0aW9uZyAqLwogICAgICAgIGlmICgoYSA9IG1hbGxvYyhzaXplb2YoaW50KSAqIG4gKiAyKSkgIT0gMCkgewogICAgICAgICAgZm9yIChpID0gMDsgaSA8IG47IGkrKykKICAgICAgICAgICAgYVtpXSA9IC0xOwogICAgICAgICAgY291bnRlcjEgPSBjb3VudGVyMiA9IDA7CiAgICAgICAgICByb290ID0gMDsKICAgICAgICAgIGYoMCwgYSwgbiwgd29yaywgJnJvb3QpOwogICAgICAgICAgcHJpbnRmKCJ1bmlxOiAlZCwgYWxsOiVkLCAiLCBjb3VudGVyMSwgY291bnRlcjIpOwogICAgICAgICAgcHJpbnRmKCJ0aW1lOiAlZFxuIiwgdGltZSgmdDIpIC0gdCk7IGZmbHVzaChzdGRvdXQpOwogICAgICAgICAgcmVsZWFzZSgmcm9vdCk7CiAgICAgICAgICBmcmVlKGEpOwogICAgICAgIH0KICAgICAgfQogICAgICAvKiByZWxlYXNlIHdvcmsgYXJlYSAqLwogICAgICBmb3IgKGsgPSAwOyBrIDwgbjsgaysrKQogICAgICAgIGZyZWUod29ya1trXSk7CiAgICAgIGZyZWUod29yayk7CiAgICB9CiAgfQogIHJldHVybiAwOwp9Ci8qIGVuZCAqLwo=