先给出代码:
type arry1=array[1..15,1..15] of integer;
var a:array[1..5] of array[1..5,1..5] of integer;
pand:array[1..5] of boolean;
x,y,black:array[1..5] of integer;
c:arry1;
ch:char;
len,xx,yy,n,i,j,xa,ya,k:integer;
procedure print;
var i,j:integer;
begin for i:=1 to len do
begin for j:=1 to len do write(c[i,j]);
writeln;
end;
end;
procedure get;
var i,j,qq:integer;
begin
qq:=0;
for i:=1 to len do
begin if qq=-1 then break;
for j:=1 to len do
if c[i,j]=0 then begin xx:=i;yy:=j;qq:=-1;break;end;
end;
end;
procedure get2(j:integer);
var i,k,qq:integer;
begin
qq:=0;
for i:=1 to x[j] do
begin if qq=-1 then break;
for k:=1 to y[j] do
if a[j][i,k]<>0 then begin xa:=i;ya:=k;qq:=-1;break;end;
end;
end;
function tian(j:integer):boolean;
var b:arry1;
qi,mo,tt,tc,dd:integer;
begin
if black[j]=0 then exit(true);
b:=c;
get;
get2(j);
for qi:=1 to x[j] do
begin tt:=xx+qi-xa;
for mo:=1 to y[j] do
begin tc:=mo+yy-ya;
if (tt>len)or(tt<1)or(tc>len)or(tc<1) then
begin if a[j][qi,mo]<>0 then begin c:=b;exit(false);end
else continue;
end
else
if a[j][qi,mo]*c[tt,tc]<>0 then begin c:=b;exit(false);end
else
if a[j][qi,mo]<>0 then c[tt,tc]:=a[j][qi,mo];
end;
end;
exit(true);
end;
procedure work(i:integer);
var cctv:arry1;
j:integer;
begin
if i>n then begin print;halt;end;
for j:=1 to n do
if pand[j] then begin cctv:=c;
if tian(j) then begin pand[j]:=false;
work(i+1);
pand[j]:=true;
c:=cctv;
end;
end;
end;
begin
readln(n);
for i:=1 to n do
begin readln(x[i],y[i]);
for j:=1 to x[i] do
begin
for k:=1 to y[i] do
begin
read(ch);
a[i][j,k]:=ord(ch)-ord(0);
if a[i][j,k]=1 then
begin inc(len);inc(black[i]);a[i][j,k]:=i;end;
end;
readln;
end;
end;
i:=len;
len:=round(sqrt(len));
fillchar(pand,sizeof(pand),true);
if i=len*len then work(1);
writeln(No solution possible);
end.
基本思路就是寻找一个”左上角,就是过程get
和get1(j);get是用来寻找拼图的左上角,返回(xx,yy),get1(j)用来求第j块拼块的左上角(xa,ya),而且两者的过程也是有区别的,要注意。
work是一个搜索过程,个人认为函数tian(j)更重要。
为了便于理解,我举一个例子。比如当前已经拼好一半的拼图是图一:
1110
1000
0011
0011
现在我们目的是要看看拼块图二是否匹配,
图二:
001
111
利用get,我们返回图一的“左上角”坐标(1,4);
利用get1(j),我们返回图二的“左上角”(1,3);
(我再次强调get1与get的区别)
我们将(1,4)与(1,3)匹配,发现其余的部分也匹配,所以tian(j)不仅把图二拼到图一里,还返回了true供work进入下一层。
时间效率相对而言还是比较高的,甚至数据规模扩大一倍也还是可能通过的,当然,值得优化的地方还有很多,我就不再展开。
http://blog.sina.com.cn/s/blog_4c2ac4ef01008ljh.html