package csm.work;
import java.util.Random;
public class Question_9 {
/*
* 题目:Ex. 对8皇后问题,写一算法,求n=12~20时最优的StepVegas值(lasvegas Algorithm)。
* 思路:求解规模为15的八皇后问题,随机放置k个八皇后,对余下的20-k个皇后用回溯法放置,找出一个解则结束 结果如下:
*
规模为15,随机放置0个,平均运行时间为:3506690ns
找到解的成功率为1.0,随机算法的超时率为0.0
规模为15,随机放置1个,平均运行时间为:2808510ns
找到解的成功率为1.0,随机算法的超时率为0.0
规模为15,随机放置2个,平均运行时间为:1695070ns
找到解的成功率为1.0,随机算法的超时率为0.0
规模为15,随机放置3个,平均运行时间为:1229860ns
找到解的成功率为1.0,随机算法的超时率为0.0
规模为15,随机放置4个,平均运行时间为:978460ns
找到解的成功率为1.0,随机算法的超时率为0.0
规模为15,随机放置5个,平均运行时间为:708120ns
找到解的成功率为0.988,随机算法的超时率为0.0
规模为15,随机放置6个,平均运行时间为:464840ns
找到解的成功率为0.755,随机算法的超时率为0.0
规模为15,随机放置7个,平均运行时间为:201980ns
找到解的成功率为0.356,随机算法的超时率为0.0
规模为15,随机放置8个,平均运行时间为:82830ns
找到解的成功率为0.105,随机算法的超时率为0.0
规模为15,随机放置9个,平均运行时间为:46240ns
找到解的成功率为0.039,随机算法的超时率为0.0
规模为15,随机放置10个,平均运行时间为:40850ns
找到解的成功率为0.025,随机算法的超时率为0.0
规模为15,随机放置11个,平均运行时间为:50650ns
找到解的成功率为0.011,随机算法的超时率为0.01
规模为15,随机放置12个,平均运行时间为:156030ns
找到解的成功率为0.0060,随机算法的超时率为0.19
规模为15,随机放置13个,平均运行时间为:1221120ns
找到解的成功率为0.0040,随机算法的超时率为2.85
规模为15,随机放置14个,平均运行时间为:3344020ns
找到解的成功率为0.0030,随机算法的超时率为8.09
从数据可以看出,放置5-6个时性能较优
*/
public static Random r = new Random();
public static int size = 15;
// 放置20个皇后的坐标
public int x[] = new int[size];
public int y[] = new int[size];
public int num = 0;
public int k;
// 检测两皇后是否符合规则
static boolean check(int x1, int y1, int x2, int y2) {
if (x1 != x2 && y1 != y2 && (x1 + y1) != (x2 + y2)
&& (x1 - y1) != (x2 - y2))
return true;
return false;
}
// 判断某点是否可放
boolean isValid(int x1, int y1) {
for (int i = 0; i < num; i++) {
if (!check(x1, y1, x[i], y[i])) {
return false;
}
}
return true;
}
public boolean stepVegas(int k1) {
k = k1;
int limit = 10000;
while (k1 != 0 && limit != 0) {
int x1 = r.nextInt(size);
int y1 = r.nextInt(size);
/*
* x1 = 0; y1 = 2; if(k1==1) { x1 = 3; y1 = 0; }
*/
if (isValid(x1, y1)) {
// System.out.println(x1+","+y1);
x[num] = x1;
y[num] = y1;
num++;
k1--;
}
limit--;
}
if (limit == 0)
return false;
return true;
}
// 回溯
public boolean backTrace() {
int validx[] = new int[size - k];
int validy[] = new int[size - k];
int flag[] = new int[size];
for (int i = 0; i < k; i++) {
flag[x[i]] = 1;
}
int index = 0;
for (int i = 0; i < size; i++) {
if (flag[i] == 0) {
validx[index] = i;
validy[index] = -1;
index++;
}
}
// show();
for (int i = 0; i < index; i++) {
int j;
for (j = validy[i] + 1; j < size; j++) {
if (isValid(validx[i], j)) {
x[num] = validx[i];
y[num] = j;
num++;
if (num == size)
return true;
validy[i] = j;
for (int m = i + 1; m < size - k; m++) {
validy[m] = -1;
}
// show();
break;
}
}
if (j == size) {
if (num == k)
return false;
num--;
i -= 2;
// show();
}
}
return false;
}
public void show() {
System.out.println("****************************");
int flag[][] = new int[size][size];
for (int i = 0; i < num; i++) {
flag[x[i]][y[i]] = 1;
}
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
System.out.print(flag[i][j]);
}
System.out.println();
}
}
public static void main(String[] args) {
// 规模为15,随机放置3、6、9个八皇后的性能比较,每个运行100次。
long begin, end;
int success, failed, timeout;
int testCount = 1000;
for (int j = 0; j < Question_9.size; j++) {
success = 0;
failed = 0;
timeout = 0;
begin = System.nanoTime();
for (int i = 0; i < testCount; i++) {
Question_9 q9 = new Question_9();
if (q9.stepVegas(j)) {
if (q9.backTrace()) {
success++;
} else {
failed++;
}
} else {
timeout++;
}
}
end = System.nanoTime();
System.out.println("规模为15,随机放置"+j+"个,平均运行时间为:" + (end - begin) / 100
+ "ns");
System.out.println("找到解的成功率为" + (success / (testCount * 1.0))
+ ",随机算法的超时率为" + (timeout / 100.0));
System.out.println();
}
}
}
import java.util.Random;
public class Question_9 {
/*
* 题目:Ex. 对8皇后问题,写一算法,求n=12~20时最优的StepVegas值(lasvegas Algorithm)。
* 思路:求解规模为15的八皇后问题,随机放置k个八皇后,对余下的20-k个皇后用回溯法放置,找出一个解则结束 结果如下:
*
规模为15,随机放置0个,平均运行时间为:3506690ns
找到解的成功率为1.0,随机算法的超时率为0.0
规模为15,随机放置1个,平均运行时间为:2808510ns
找到解的成功率为1.0,随机算法的超时率为0.0
规模为15,随机放置2个,平均运行时间为:1695070ns
找到解的成功率为1.0,随机算法的超时率为0.0
规模为15,随机放置3个,平均运行时间为:1229860ns
找到解的成功率为1.0,随机算法的超时率为0.0
规模为15,随机放置4个,平均运行时间为:978460ns
找到解的成功率为1.0,随机算法的超时率为0.0
规模为15,随机放置5个,平均运行时间为:708120ns
找到解的成功率为0.988,随机算法的超时率为0.0
规模为15,随机放置6个,平均运行时间为:464840ns
找到解的成功率为0.755,随机算法的超时率为0.0
规模为15,随机放置7个,平均运行时间为:201980ns
找到解的成功率为0.356,随机算法的超时率为0.0
规模为15,随机放置8个,平均运行时间为:82830ns
找到解的成功率为0.105,随机算法的超时率为0.0
规模为15,随机放置9个,平均运行时间为:46240ns
找到解的成功率为0.039,随机算法的超时率为0.0
规模为15,随机放置10个,平均运行时间为:40850ns
找到解的成功率为0.025,随机算法的超时率为0.0
规模为15,随机放置11个,平均运行时间为:50650ns
找到解的成功率为0.011,随机算法的超时率为0.01
规模为15,随机放置12个,平均运行时间为:156030ns
找到解的成功率为0.0060,随机算法的超时率为0.19
规模为15,随机放置13个,平均运行时间为:1221120ns
找到解的成功率为0.0040,随机算法的超时率为2.85
规模为15,随机放置14个,平均运行时间为:3344020ns
找到解的成功率为0.0030,随机算法的超时率为8.09
从数据可以看出,放置5-6个时性能较优
*/
public static Random r = new Random();
public static int size = 15;
// 放置20个皇后的坐标
public int x[] = new int[size];
public int y[] = new int[size];
public int num = 0;
public int k;
// 检测两皇后是否符合规则
static boolean check(int x1, int y1, int x2, int y2) {
if (x1 != x2 && y1 != y2 && (x1 + y1) != (x2 + y2)
&& (x1 - y1) != (x2 - y2))
return true;
return false;
}
// 判断某点是否可放
boolean isValid(int x1, int y1) {
for (int i = 0; i < num; i++) {
if (!check(x1, y1, x[i], y[i])) {
return false;
}
}
return true;
}
public boolean stepVegas(int k1) {
k = k1;
int limit = 10000;
while (k1 != 0 && limit != 0) {
int x1 = r.nextInt(size);
int y1 = r.nextInt(size);
/*
* x1 = 0; y1 = 2; if(k1==1) { x1 = 3; y1 = 0; }
*/
if (isValid(x1, y1)) {
// System.out.println(x1+","+y1);
x[num] = x1;
y[num] = y1;
num++;
k1--;
}
limit--;
}
if (limit == 0)
return false;
return true;
}
// 回溯
public boolean backTrace() {
int validx[] = new int[size - k];
int validy[] = new int[size - k];
int flag[] = new int[size];
for (int i = 0; i < k; i++) {
flag[x[i]] = 1;
}
int index = 0;
for (int i = 0; i < size; i++) {
if (flag[i] == 0) {
validx[index] = i;
validy[index] = -1;
index++;
}
}
// show();
for (int i = 0; i < index; i++) {
int j;
for (j = validy[i] + 1; j < size; j++) {
if (isValid(validx[i], j)) {
x[num] = validx[i];
y[num] = j;
num++;
if (num == size)
return true;
validy[i] = j;
for (int m = i + 1; m < size - k; m++) {
validy[m] = -1;
}
// show();
break;
}
}
if (j == size) {
if (num == k)
return false;
num--;
i -= 2;
// show();
}
}
return false;
}
public void show() {
System.out.println("****************************");
int flag[][] = new int[size][size];
for (int i = 0; i < num; i++) {
flag[x[i]][y[i]] = 1;
}
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
System.out.print(flag[i][j]);
}
System.out.println();
}
}
public static void main(String[] args) {
// 规模为15,随机放置3、6、9个八皇后的性能比较,每个运行100次。
long begin, end;
int success, failed, timeout;
int testCount = 1000;
for (int j = 0; j < Question_9.size; j++) {
success = 0;
failed = 0;
timeout = 0;
begin = System.nanoTime();
for (int i = 0; i < testCount; i++) {
Question_9 q9 = new Question_9();
if (q9.stepVegas(j)) {
if (q9.backTrace()) {
success++;
} else {
failed++;
}
} else {
timeout++;
}
}
end = System.nanoTime();
System.out.println("规模为15,随机放置"+j+"个,平均运行时间为:" + (end - begin) / 100
+ "ns");
System.out.println("找到解的成功率为" + (success / (testCount * 1.0))
+ ",随机算法的超时率为" + (timeout / 100.0));
System.out.println();
}
}
}