关于tju1258双向宽搜的做法讨论
于是,我又想到了反向宽搜,这样的好处是一次搜完:
程序如下:
const dbin:array[1..8]of longint=(1,2,6,24,120,720,5040,40320);
maxn=362880;
maxmm=2;
var restate:array[1..maxn]of boolean;
numstep:array[1..maxn]of longint;
queue:array[1..maxn,1..2]of longint;
mat:array[0..maxmm,1..9]of integer;
tmpline:array[1..9]of integer;
recode,tmpstate,co,qf,qr,s:longint;
procedure init;
begin
qf:=0;qr:=0;
end;
procedure turncode(num:integer;var code:longint);
var s,s1:integer;
sum:longint;
begin
sum:=1;
for s:=1 to 8 do
begin
inc(sum,(mat[num,s])*dbin[9-s]);
for s1:=s+1 to 9 do if mat[num,s1]>mat[num,s]then dec(mat[num,s1]);
end;
code:=sum;
end;
procedure turnmat(num:integer;code:longint);
var add,dnum,s,s1:integer;
tmp:longint;
begin
tmp:=code-1;
for s:=8 downto 0 do
begin
if s>0 then
begin
tmpline[9-s]:=tmp div dbin[s]+1;
dnum:=tmpline[9-s];
tmp:=tmp mod dbin[s];
end else dnum:=1;
for s1:=8-s downto 1 do if dnum>=tmpline[s1] then inc(dnum);
mat[num,9-s]:=dnum-1;
end;
end;
procedure inqueue(d1,d2:longint);
begin
inc(qr);
queue[qr,1]:=d1;
queue[qr,2]:=d2;
end;
procedure outqueue(var d1,d2:longint);
begin
inc(qf);
if qf>qr then
begin
d1:=-1;
exit;
end;
d1:=queue[qf,1];
d2:=queue[qf,2];
end;
procedure change(num1,num2,op:integer);
var tt:integer;
begin
mat[num2]:=mat[num1];
if op=1 then
begin
tt:=mat[num2,4];mat[num2,4]:=mat[num2,5];
mat[num2,5]:=mat[num2,6];mat[num2,6]:=tt;
end else
begin
tt:=mat[num2,1];mat[num2,1]:=mat[num2,2];mat[num2,2]:=mat[num2,3];
mat[num2,3]:=mat[num2,6];mat[num2,6]:=mat[num2,9];
mat[num2,9]:=mat[num2,8];mat[num2,8]:=mat[num2,7];
mat[num2,7]:=mat[num2,4];mat[num2,4]:=tt;
end;
end;
begin
init;
tmpstate:=1;
restate[1]:=true;
inqueue(tmpstate,0);
outqueue(tmpstate,co);
while tmpstate<>-1 do
begin
turnmat(1,tmpstate);
for s:=1 to 2 do
begin
change(1,2,s);
turncode(2,recode);
if not restate[recode] then
begin
restate[recode]:=true;
numstep[recode]:=co+1;
inqueue(recode,co+1);
end;
end;
outqueue(tmpstate,co);
end;
writeln('done');
while not seekeof do
begin
readln(mat[1,1],mat[1,2],mat[1,3]);
readln(mat[1,4],mat[1,5],mat[1,6]);
readln(mat[1,7],mat[1,8],mat[1,9]);
turncode(1,recode);
if not restate[recode] then writeln('UNSOLVABLE') else writeln(numstep[recode]);
end;
end.
用一个数组记录下所有情况,以后就直接用.
TLE得我郁闷.
不过,我发现了一个结论:一就是刚才所说的32层,另一个就是...没有无解情况...很奇怪吧?不过也是自然的:因为你可以试一试任何一个数都能移到其他任意位置.就是这样...
所以...Go away..."UNSOLVABLE"!!!!
很自然就想到了双向宽搜.
为了避免作弊我暂时不给出程序.
但是,我提供一些数据:
设一个反向搜索的maxdepth,则:
time>2000ms(maxdepth<=12)
time=1400ms(maxdepth=13)
time<1s(14<=maxdepth<=31,都能ac)
从理论上说,maxdepth=32/2=16时,时间是最优的,我当时取的16,ac360ms
但是,因为是多组数据,就不一定了,经过测试,当maxdepth=18时,time<260ms
这里费了不少心血,就是把一个3*3的方阵压缩成一个1-9!的一个一一对应的数.
procedure turncode(num:integer;var code:longint);
var s,s1:integer;
sum:longint;
begin
sum:=1;
for s:=1 to 9 do mat[0,s]:=mat[num,s]+1;
for s:=1 to 8 do
begin
inc(sum,(mat[0,s]-1)*dbin[9-s]);
for s1:=s+1 to 9 do if mat[0,s1]>mat[0,s]then dec(mat[0,s1]);
end;
code:=sum;
end;
procedure turnmat(num:integer;code:longint);
var add,dnum,s,s1:integer;
tmp:longint;
begin
tmp:=code-1;
for s:=8 downto 0 do
begin
if s>0 then
begin
tmpline[9-s]:=tmp div dbin[s]+1;
dnum:=tmpline[9-s];
tmp:=tmp mod dbin[s];
end else dnum:=1;
for s1:=8-s downto 1 do if dnum>=tmpline[s1] then inc(dnum);
mat[num,9-s]:=dnum-1;
end;
end;
实际上这是一个O(40)的算法.不够好.
谁能给出更快的压缩方法请指点,如一个O(9)的
拜托了....
给程序吧...不然有人不服气
const dbin:array[1..8]of longint=(1,2,6,24,120,720,5040,40320);
maxn=362880;
maxmm=2;
maxbdep=16 (18);
var restate:array[1..maxn]of boolean;
restate2:array[1..maxn]of boolean;
numstep:array[1..maxn]of longint;
queue:array[1..maxn,1..2]of longint;
mat:array[0..maxmm,1..9]of integer;
tmpline:array[1..9]of integer;
recode,tmpstate,co,qf,qr,s:longint;
procedure init;
begin
qf:=0;qr:=0;
end;
procedure turncode(num:integer;var code:longint);
var s,s1:integer;
sum:longint;
begin
sum:=1;
for s:=1 to 8 do
begin
inc(sum,(mat[num,s])*dbin[9-s]);
for s1:=s+1 to 9 do if mat[num,s1]>mat[num,s]then dec(mat[num,s1]);
end;
code:=sum;
end;
procedure turnmat(num:integer;code:longint);
var add,dnum,s,s1:integer;
tmp:longint;
begin
tmp:=code-1;
for s:=8 downto 0 do
begin
if s>0 then
begin
tmpline[9-s]:=tmp div dbin[s]+1;
dnum:=tmpline[9-s];
tmp:=tmp mod dbin[s];
end else dnum:=1;
for s1:=8-s downto 1 do if dnum>=tmpline[s1] then inc(dnum);
mat[num,9-s]:=dnum-1;
end;
end;
procedure inqueue(d1,d2:longint);
begin
inc(qr);
queue[qr,1]:=d1;
queue[qr,2]:=d2;
end;
procedure outqueue(var d1,d2:longint);
begin
inc(qf);
if qf>qr then
begin
d1:=-1;
exit;
end;
d1:=queue[qf,1];
d2:=queue[qf,2];
end;
procedure changeback(num1,num2,op:integer);
var tt:integer;
begin
mat[num2]:=mat[num1];
if op=1 then
begin
tt:=mat[num2,4];mat[num2,4]:=mat[num2,5];
mat[num2,5]:=mat[num2,6];mat[num2,6]:=tt;
end else
begin
tt:=mat[num2,1];mat[num2,1]:=mat[num2,2];mat[num2,2]:=mat[num2,3];
mat[num2,3]:=mat[num2,6];mat[num2,6]:=mat[num2,9];
mat[num2,9]:=mat[num2,8];mat[num2,8]:=mat[num2,7];
mat[num2,7]:=mat[num2,4];mat[num2,4]:=tt;
end;
end;
procedure change(num1,num2,op:integer);
var tt:integer;
begin
mat[num2]:=mat[num1];
if op=1 then
begin
tt:=mat[num2,6];mat[num2,6]:=mat[num2,5];
mat[num2,5]:=mat[num2,4];mat[num2,4]:=tt;
end else
begin
tt:=mat[num2,1];mat[num2,1]:=mat[num2,4];mat[num2,4]:=mat[num2,7];
mat[num2,7]:=mat[num2,8];mat[num2,8]:=mat[num2,9];
mat[num2,9]:=mat[num2,6];mat[num2,6]:=mat[num2,3];
mat[num2,3]:=mat[num2,2];mat[num2,2]:=tt;
end;
end;
begin
init;
tmpstate:=1;
restate[1]:=true;
inqueue(tmpstate,0);
outqueue(tmpstate,co);
while tmpstate<>-1 do
begin
turnmat(1,tmpstate);
for s:=1 to 2 do
begin
changeback(1,2,s);
turncode(2,recode);
if not restate[recode] then
begin
restate[recode]:=true;
numstep[recode]:=co+1;
if co<maxbdep then inqueue(recode,co+1);
end;
end;
outqueue(tmpstate,co);
end;
while not seekeof do
begin
init;
fillchar(restate2,sizeof(restate2),false);
readln(mat[1,1],mat[1,2],mat[1,3]);
readln(mat[1,4],mat[1,5],mat[1,6]);
readln(mat[1,7],mat[1,8],mat[1,9]);
turncode(1,recode);
tmpstate:=recode;
inqueue(tmpstate,0);
outqueue(tmpstate,co);
while tmpstate<>-1 do
begin
turnmat(1,tmpstate);
if restate[tmpstate] then break;
for s:=1 to 2 do
begin
change(1,2,s);
turncode(2,recode);
if not restate2[recode] then
begin
restate2[recode]:=true;
inqueue(recode,co+1);
end;
end;
outqueue(tmpstate,co);
end;
writeln(numstep[tmpstate]+co);
end;
end.
http://bbs.cqyzedu.com/dispbbs.asp?boardid=24&id=4142
评论