我正在尝试生成具有更强条件的n-queen实例,以便没有3个皇后在同一行。
这是,如果(r0, c0), (r1, c1), (r2, c2)
是皇后的三个独特位置,
然后(c0 - c1) * (r0 - r2) != (c0 - c2) * (r0 - r1)
。
现在,我正在尝试使用简单的随机爬山在每次迭代中交换两行,以便减少冲突的数量。使用这个,我能够解决到n~200。
#include <cstdio>
#include <cstdlib>
#include <ctime>
class Board{
public:
int size;
int * ar;
Board(int size): size(size){
ar = new int[size];
for(int i=0;i<size;i++){
ar[i] = i+1;
}
for(int i=0;i<size*50;i++){
cell_swap(rand() % size, i % size);
}
}
void cell_swap(int a, int b){
if(a == b) return;
ar[a] ^= ar[b];
ar[b] ^= ar[a];
ar[a] ^= ar[b];
}
int clash_count(int i){
int count = 0;
for(int j=0;j<size;j++){
if(i==j) continue;
for(int k=j+1;k<size;k++){
if(i==k) continue;
if((i-k)*(ar[i]-ar[j]) == (i-j)*(ar[i]-ar[k])){
count++;
}
}
}
return count;
}
void print(){
for(int i=0;i<size;i++){
printf("%4d", ar[i]);
}
printf("\n");
}
~Board(){
delete[] ar;
}
};
int main(int argc, char *argv[]){
srand(time(NULL));
int size = argc > 1 ? atoi(argv[1]) : 10;
Board * b = new Board(size);
bool flag = 0;
while(1){
// b->print();
int clashes[size];
int total_clash = 0;
for(int i=0;i<size;i++){
clashes[i] = b->clash_count(i);
total_clash += clashes[i];
}
total_clash /= 3;
printf("clash: %d\n", total_clash);
if(total_clash == 0) break;
int moves[(size*(size-1))<<1][3];
int ix = 0;
int s = 0;
for(int i=0;i<size;i++){
for(int j=0;j<size;j++){
b->cell_swap(i, j);
moves[ix][0] = clashes[i] + clashes[j];
moves[ix][0] -= b->clash_count(i);
moves[ix][0] -= b->clash_count(j);
if(moves[ix][0] > 0){
s += moves[ix][0];
moves[ix][1] = i;
moves[ix][2] = j;
ix++;
}
b->cell_swap(i, j);
}
}
if(s == 0) continue;
int rand_ = rand() % s;
int s_ = 0;
for(int i=0;i<ix;i++){
if(moves[i][0] < 0) continue;
s_ += moves[i][0];
if(s_ > rand_){
b->cell_swap(moves[i][1], moves[i][2]);
break;
}
}
}
b->print();
return 0;
}
我想扩展我的算法。我想减少发现冲突的运行时间。无论如何要提高每次迭代的复杂性?