主题:[原创]概率算法—n皇后问题拉斯维加斯算法优化
jtchang
[专家分:5370] 发布于 2006-03-03 19:06:00
最近心情不好,离开论坛一段时间。最后给大家贴个以前编的程序,n皇后问题的概率解法。
【问题】
在n*n的棋盘上,放上n个皇后,按国际象棋规则,没有任何两个皇后会互相攻击。
【要求】
打印出其中一种摆放的方法。
考虑n较大时(例如n=100)时程序得到答案的速度问题。
【程序所用的算法提示】
1、拉斯维加斯概率算法
每一行得到了几个摆放位置时,不是按顺序进行摆放,而是随机摆放的。因此程序每次运行的时间都不一样。用拉斯维加斯算法除非找不到解,如果找到,答案就一定是正确的。
2、优化算法
这是我修改的算法。标准拉斯维加斯算法的特点是:当无法继续往下摆放时,就从头重新开始。我修改后的方法是:类似回溯,但实际上是“伪回溯”。无论在哪一行受阻无法摆放,第1次受阻后退1行继续摆;第2次受阻后退2行继续摆;依此类推。
回复列表 (共7个回复)
沙发
jtchang [专家分:5370] 发布于 2006-03-03 19:07:00
【源程序】
(*
One Answer Of N Queens Problem.
Arithmetic Of j.t.Chang's LV.
*)
program LV_Queens;
uses crt,dos;
const
M=10000;
var
x:array[1..M] of integer;
i:integer;
h1,m1,s1,hund1,
h2,m2,s2,hund2:word;
N: integer;
procedure PrintResult;
var
i,j: integer;
t1,t2:longint;
f:text;
ch: char;
begin
gettime(h2,m2,s2,hund2);
if (h2<h1) then h2:=h2+24;
t1:=1; t2:=1;
t1:=t1*s1*100+t1*m1*60*100+t1*h1*3600*100+hund1;
t2:=t2*s2*100+t2*m2*60*100+t2*h2*3600*100+hund2;
t1:=t2-t1;
hund1:=t1 mod 100; t1:=t1 div 100;
s1:=t1 mod 60; t1:=t1 div 60;
m1:=t1 mod 60; t1:=t1 div 60;
h1:=t1; writeln;
write('One answer found. Used time: ');
write(h1 div 10, h1 mod 10, ':');
write(m1 div 10, m1 mod 10, ':');
write(s1 div 10, s1 mod 10, '.');
writeln(hund1 div 10,hund1 mod 10);
write('Press any key to view result... ');
ch:=readkey; writeln;
for i:=1 to N do
begin
for j:=1 to N do
if j=x[i] then write ('Q':2)
else write('.':2) ;
writeln;
end;
writeln;
for i:=1 to N do write(x[i]:5);
writeln; writeln;
write('Save result to file (y/n)? ');
ch:=readkey; writeln(ch);
if upcase(ch)='Y' then
begin
assign(f,'QUEENS.TXT');
rewrite(f);
writeln(f,'One answer of ',N,' queens problem: ');
writeln(f);
for i:=1 to N do
begin
write(f,x[i]:5);
if i mod 16=0 then writeln(f);
end;
writeln(f);
close(f);
writeln('Result save to file: QUEENS.TXT');
end;
end;
function place(k,a:integer):boolean;
var
i:integer;
begin
for i:=1 to k-1 do
if (k-i)=abs(a-x[i]) then
begin
place:=false;
exit;
end;
place:=true;
end;
procedure queensLV;
var
i,j,k,c,t,stop: integer;
begin
for i:=1 to N do x[i]:=i;
k:=1; c:=1; stop:=1;
randomize;
while (k<=N) do
begin
c:=0;
for j:=k to N do
if place(k,x[j]) then
begin
c:=c+1;
if random(c)=0 then t:=j;
end;
if c>0 then
begin
if(t<>k) then
begin
x[k]:=x[k] xor x[t];
x[t]:=x[t] xor x[k];
x[k]:=x[k] xor x[t];
end;
k:=k+1;
end
else
begin
k:=k-stop;
stop:=stop+1;
if k<1 then
begin
k:=1;
stop:=1;
end;
end;
end;
end;
begin
clrscr;
writeln;
writeln('N Queens Problem.');
writeln('Programmed by j.t.Chang.');
writeln;
write('Enter N (N>=4): '); readln(N);
if (N<4) or (N>M) then
begin
writeln('Out of range: 4..',M);
halt;
end;
writeln('Finding one answer of ',N,' queens problem.');
writeln('Please wait...');
gettime(h1,m1,s1,hund1);
for i:=1 to N do x[i]:=0;
queensLV;
PrintResult;
end.
板凳
47 [专家分:590] 发布于 2006-03-03 23:54:00
恩恩恩
8错
值得学习!!比如那个伪回溯。
3 楼
hevole [专家分:70] 发布于 2006-04-04 14:09:00
我不明白
为什么要那样回溯呢?
4 楼
日暮霜林 [专家分:0] 发布于 2006-04-17 21:59:00
若要
5 楼
日暮霜林 [专家分:0] 发布于 2006-04-17 22:00:00
求所有解是否会数据太大?
6 楼
diaoxue [专家分:600] 发布于 2007-12-27 11:43:00
贴个c++语言版的
#include <iostream>
#include <ctime>
#include <cmath>//in vc 6.0
using namespace std;
const int n=8;
int t=3;
int x[n+1];//don't use x[0]
int bestx[n+1];//don't use bestx[0]
long sum=0;
bool Place(int k)
{
for(int j=1;j<k;j++)
{
if(abs(k-j)==abs(x[k]-x[j]) || x[j]==x[k])//不符合条件 返回假
return false;
}
return true;
}
int Rand(int m)
{
srand((unsigned) time(NULL));
return rand()%m;
}
bool Queenslv(int stop)
{
int k=1;
int count=1;
while((k<stop) && (count>0))
{
count=0;
int j=0;
for(int i=0;i<n;i++)
{
x[k]=i;
if(Place(k))
if(Rand(++count)==0)
j=i;
}
if(count>0)
x[k++]=j;
}
return (count>0);
}
void QueenTB(int t)
{
if(t>n)
{
sum++;
for(int j=1;j<=n;j++)//更新记录,输出
{
bestx[j]=x[j];
cout<<bestx[j]<<"\t";
}
cout<<endl;
}
else
{
for(int i=1;i<=n;i++)
{
x[t]=i;
if(Place(t))QueenTB(t+1);
}
}
}
void Nqueen()
{
int stop=3;
while(!Queenslv(stop));
QueenTB(stop);
// {
// for(int i=0;i<n;i++)
// cout<<bestx[i]<<"\t";
// cout<<endl;
// }
}
int main()
{
// QueenTB(t);
Nqueen();
cout<<sum;
cout<<endl;
return 0;
}
7 楼
diaoxue [专家分:600] 发布于 2007-12-27 11:46:00
stop越大,得到结果的概率越小
取7、8时要多试几次,有的解也很少,这时效率并不好
一般取3比较好
我来回复