import java.io.Serializable;
import com.ibm.apgas.Pool;
import com.ibm.apgas.Task;
public class NQueens {
public static int[] expectedSolutions = new int[] { 0, 1, 0, 0, 2, 10, 4, 40, 92, 352, 724, 2680, 14200, 73712, 365596, 2279184, 14772512 };
public static int numSolutions = 0;
public static void main(String[] args) {
final int n = args.length > 0 ? Integer.parseInt(args[0]) : 8;
Pool p = new Pool(new Task() {
public void body() {
solveNQueens(n);
}
});
p.start();
}
static void solveNQueens(final int n) {
long start = System.nanoTime();
Pool.runFinish(new Task(){
public void body() {
int P = Pool.numPlaces();
int baseSize = n / P;
int extra = n - (baseSize*P);
for (int i=0; i<P; i++) {
final int start = i*baseSize + (i<extra ? i : extra);
final int end = start+baseSize+(i<extra ? 0 : -1);
Pool.runAsync(i, new Task() {
public void body() {
new Board(n).search(start, end);
if (Pool.here() != 0) reportResult();
}
void reportResult() {
final int tmp = numSolutions;
Pool.runAsync(0, new Task(){
public void body() {
addSolutions(tmp);
}});
}
});
}
}});
long stop = System.nanoTime();
boolean correct = numSolutions == expectedSolutions[n];
double time = ((double)(stop - start)) / 1e9;
System.out.println("NQueens "+n+"(P = "+Pool.numPlaces()+") has "+numSolutions+" solutions "+
(correct ? "(ok)." : "(wrong).")+" Time "+time+" seconds");
}
static synchronized void addSolutions(int n) {
numSolutions += n;
}
static class Board implements Serializable {
int n;
int[] q;
Board(int n) {
this.n = n;
q = new int[0];
}
Board(int n, int[] old, int newQ) {
this.n = n;
int[] tmp = new int[old.length+1];
System.arraycopy(old, 0, tmp, 0, old.length);
tmp[old.length] = newQ;
q = tmp;
}
boolean safe(int j) {
int n = q.length;
for (int k=0; k<n; k++) {
if (j == q[k] || Math.abs(n-k) == Math.abs(j-q[k])) return false;
}
return true;
}
void search(int low, int high) {
for (int k=low; k<=high; k++) {
if (safe(k)) {
new Board(n, q, k).search();
}
}
}
void search() {
if (q.length == n) {
addSolutions(1);
} else {
search(0, n-1);
}
}
}
}