#include <stdio.h>
#include <memory.h>
#include <time.h>
#include <stdlib.h>
const char iname[] = "dame.in";
const char oname[] = "dame.out";
#define MAXN 1007
void print(int n, int queen[])
{
FILE *fo = fopen(oname, "w");
fprintf(fo, "%d\n", n);
for (int i = 1; i <= n; ++ i)
fprintf(fo, "%d %d\n", i, queen[i]);
fclose(fo);
}
void perform_swap(int i, int j, int n, int queen[], int dn[], int dp[])
{
int temp;
dn[i + queen[i]] --;
dp[i - queen[i] + n] --;
dn[j + queen[j]] --;
dp[j - queen[j] + n] --;
temp = queen[i], queen[i] = queen[j], queen[j] = temp;
dn[i + queen[i]] ++;
dp[i - queen[i] + n] ++;
dn[j + queen[j]] ++;
dp[j - queen[j] + n] ++;
}
int swap(int i, int j, int n, int queen[], int dn[], int dp[], int collisions)
{
if ((i + queen[i] == j + queen[j]) || (i - queen[i] == j - queen[j]))
return collisions;
int tcollisions = collisions;
if (dn[i + queen[i]] >= 2)
tcollisions --;
if (dp[i - queen[i] + n] >= 2)
tcollisions --;
if (dn[j + queen[j]] >= 2)
tcollisions --;
if (dp[j - queen[j] + n] >= 2)
tcollisions --;
if (dn[j + queen[i]] >= 1)
tcollisions ++;
if (dp[j - queen[i] + n] >= 1)
tcollisions ++;
if (dn[i + queen[j]] >= 1)
tcollisions ++;
if (dp[i - queen[j] + n] >= 1)
tcollisions ++;
return tcollisions;
}
int compute_attacks(int n, int queen[], int dn[], int dp[], int attack[])
{
int number_of_attacks = 0;
for (int i = 1; i <= n; ++ i) {
if (dn[i + queen[i]] >= 2)
attack[number_of_attacks ++] = i;
if (dp[i - queen[i] + n] >= 2)
attack[number_of_attacks ++] = i;
}
return number_of_attacks;
}
int compute_collisions(int n, int queen[], int dn[], int dp[])
{
int collisions = 0;
for (int i = 1; i <= n; ++ i) {
dn[i + queen[i]] ++;
dp[i - queen[i] + n] ++;
}
for (int i = 2; i <= 2 * n; ++ i) {
if (dn[i] >= 2)
collisions += dn[i] - 1;
}
for (int i = 1 - n; i <= n - 1; ++ i) {
if (dp[i + n] >= 2)
collisions += dp[i + n] - 1;
}
return collisions;
}
int main(void)
{
srand((unsigned)time(0));
int n;
FILE *fi = fopen(iname, "r");
fscanf(fi, "%d", &n);
fclose(fi);
/* queen search */
int queen[MAXN];
int dn[MAXN << 1]; /* 2, .., 2*n */
int dp[MAXN << 1]; /* 1-n, .., n-1 */
int attack[MAXN];
int used_column[MAXN];
int limit, collisions, number_of_attacks, loopcount;
int C2 = 32;
double C1 = 0.45;
if (n == 2) {
queen[1] = 1, print(1, queen);
return 0;
}
if (n == 3) {
queen[1] = 1, queen[2] = 3, print(2, queen);
return 0;
}
do {
memset(used_column, 0, sizeof(used_column));
memset(dn, 0, sizeof(dn));
memset(dp, 0, sizeof(dp));
/* a random permutation of 1,..,n */
for (int i = 1; i <= n; ++ i) {
int count = rand() % (n-i+1);
for (int j = 1; j <= n; ++ j) {
if (used_column[j] == 0) {
if (count == 0) {
queen[i] = j, used_column[j] = 1;
break ;
} else
count --;
}
}
}
/* compute */
collisions = compute_collisions(n, queen, dn, dp);
limit = C1 * collisions;
number_of_attacks = compute_attacks(n, queen, dn, dp, attack);
loopcount = 0;
/* search */
while ((collisions > 0) && (loopcount <= C2 * n)) {
for (int k = 0; k < number_of_attacks; ++ k) {
int i = attack[k];
int j = (rand() % n) + 1;
int tcollisions = swap(i, j, n, queen, dn, dp, collisions);
if (tcollisions < collisions) {
collisions = tcollisions;
perform_swap(i, j, n, queen, dn, dp);
if (collisions == 0) {
print(n, queen);
return 0;
} else if (collisions < limit) {
limit = C1 * collisions;
number_of_attacks = compute_attacks(n, queen, dn, dp, attack);
}
}
}
loopcount += number_of_attacks;
}
} while (collisions > 0) ;
print(n, queen);
return 0;
}