这道题乍一看暴力都不知道怎么写,可是我们一旦把它由一列数转换为宽为4的二维图形时做法就明了了。
如:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
转换为二维时就是
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
可以看出5可以跳到1,9,6,8;6可以跳到2,5,7,10;其他的也是如此,可以走到它的上下左右四个格子。
暴力搜索肯定会超时,那么,如何优化呢?
题目要求我们将一个状态转换到另一个状态,所以我们就可以很容易的想到用估价函数来优化。
因为豹王可以从一行的最左边跳到最右边,我们便不可以用曼哈顿距离来求两点间的距离而要用连边求最短路来得到。
那么估价函数h=Σg[i,a[i]](g[i,j]代表从第i个格子到第j个格子的距离)
程序如下:
{$inline on}
const
go:array[0..3,1..4]of longint=((-3,-1,4,-4),(1,3,4,-4),(1,-1,4,-4),(1,-1,4,-4));
var
a,num:array[1..40] of longint;
g:array[-5..45,-5..45]of longint;
tot,pos,ans,n,m,i,j,k:longint;
function min (a,b:longint):longint;inline;
begin
if a<B then exit(a) else exit(b);
end;
procedure ycl;inline;
var
i,j,k:longint;
begin
fillchar(g,sizeof(g),$3f);
for i:=1 to 40 do
for j:=1 to 4 do
g[i,i+go[i mod 4,j]]:=1;
for i:=1 to 40 do
g[i,i]:=0;
for k:=1 to 40 do
for i:=1 to 40 do
for j:=1 to 40 do
g[i,j]:=min(g[i,j],g[i,k]+g[k,j]);
end;//求最短路;
function dfs(deep,gu,now,last:longint):boolean;
var
kk,x,i,j,k:longint;
begin
if gu<=0 then
exit(true);
if deep+gu>ans then
exit(false);
for i:=1 to 4 do
begin
x:=now+go[now mod 4,i];
if (x<>last)and(x>0)and(x<=n) then
begin
kk:=gu-g[x,a[x]]+g[now,a[x]];
if kk<0 then
exit(true);
a[now]:=a[x]; a[x]:=1;
if dfs(deep+1,kk,x,now) then
exit(true);
a[x]:=a[now]; a[now]:=1;
end;
end;
exit(false);
end;
procedure main;inline;
var
i,j,k:longint;
begin
j:=0;
for i:=1 to n do
j:=j+g[i,a[i]];
j:=j-g[pos,1];
writeln('Set ',tot,':');
for ans:=0 to maxlongint do
if dfs(0,j,pos,-1) then
begin
writeln(ans);
exit;
end;
end;
begin
ycl;
tot:=0;
while true do
begin
inc(tot);
readln(n);
if n=0 then
exit;
for i:=1 to n do
begin
read(a[i]);
if a[i]=1 then
pos:=i;
end;
main;
end;
end.