讨论 / 程序分析
3144046cjc 2008-05-23 04:03:00
点我顶贴 收藏 删除
囧死,本来已经打好了,提交时却提示没有登陆,结果一切热心都付诸东流,这世道,怎么好人没好报呢?另外建议renqing同志修改一下系统,应对这种情况,一流的服务还是很重要的!

先给出代码:

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进入下一层。

时间效率相对而言还是比较高的,甚至数据规模扩大一倍也还是可能通过的,当然,值得优化的地方还有很多,我就不再展开。

#1 3144046cjc@2008-02-16 18:16:00
回复 删除
详细的代码分析可以在这里看到,因为我实在懒得打,就用相机了!

http://blog.sina.com.cn/s/blog_4c2ac4ef01008ljh.html

#2 caoyuan9642@2008-05-23 04:03:00
回复 删除
"此博客不存在......"

......

查看更多回复
提交回复