[NOI导刊2011]影像之结构化特征
问题描述
在影像比对中,有一种方法是利用影像中的边缘(edge)资讯,计算每个边缘资讯中具有代表性的结构化特征,以作为比对两张影像是否相似的判断标准。Water-filling方法是从每个边缘图的一个端点开始,绕着相连的边缘点走并依序编号。若走到某一步时,遇到一个以上不同的连接点,则分成不同路径同时继续走,直到没有任何连接点为止。如果一个点和另一个点为上下左右相邻,就称为连接。
例如,在图1的影像中包含三个边缘图,每个边缘图由一些互相连接的边缘点构成。图中以黑色的方块代表边缘点,白色的方块代表背景。在Water-filling方法中,首先,从第一列(row)开始,由左至右,由上至下,先找到第一个黑点并编号为1。接着,找1的下一个尚未编号的连接点并编号为2。依此方法继续往下一个点前进依次编号。在编号6的点之后有两个尚未编号的连接点,此时,则分为两条路线,并同时编号为7继续往下走。当走到没有任何的相连点时,则结束现有边缘图的编号,并继续对影像中的其它边缘图编号。走完图1所有边缘图后所得到的编号如图2所示。所以,走完这三个边缘图所需要的步数分别为12、7及3;所以,12、7及3可以作为代表此张影像的结构化特征。请注意:位于斜对角上的两点不能算做连接,如:
请写一个程序计算每个影像中,以Water-filling方法走完其中所有的边缘图后,将每个边缘图需走的步数依走访的顺序列出。
输入说明
输入文件包含一个正方形的影像。每组影像以图的宽度n开头(l≤n≤1000)。接下来的n行代表影像的内容:0表示背景的白点,1表示黑色的边缘点。
输出说明
对每一个输入的影像,以Water-filling方法走完所有的边缘图后,先印出此张影像中共有几个边缘图。接着,将每个边缘图需走的步数按升序列出。
样例输入
10
0000000000
0011110000
0000010000
0011111000
0010110100
0010010110
0011110010
0100010010
0100000110
0100000000
样例输出
3
3
7
12
思路
是一个用来练宽搜的典型好题。你可以通过它搞懂宽搜的原理,搞懂深搜于宽搜的区别。
记录每次宽搜有多少次入队,记录一共有多少次入队。
输出入队次数的降序排列即可。
type ss=record x,y,z:longint; end; const con:array[1..2,1..4] of longint=((1,-1,0,0),(0,0,-1,1)); var a:array[0..1010,0..1010] of longint; f:array[0..1000000] of ss; b:array[0..1000000] of longint; n,i,sum,j:longint; procedure init; var ch:char; begin fillchar(a,sizeof(a),0); readln(n); for i:=1 to n do begin for j:=1 to n do begin read(ch); if ch='1' then a[i,j]:=1; end; readln; end; end; procedure sort(l,r:longint); var i,j,x,y:longint; begin i:=l;j:=r;x:=b[(l+r) div 2]; repeat while b[i]<x do inc(i); while b[j]>x do dec(j); if i<=j then begin y:=b[i]; b[i]:=b[j]; b[j]:=y; inc(i); dec(j); end; until i>j; if l<j then sort(l,j); if i<r then sort(i,r); end; procedure bfs(x,y:longint); var i,xx,yy,head,tail:longint; begin head:=0;tail:=1; f[1].x:=x;f[1].y:=y;f[1].z:=1; a[x,y]:=0; while head<tail do begin inc(head); for i:=1 to 4 do begin xx:=f[head].x+con[1,i]; yy:=f[head].y+con[2,i]; if a[xx,yy]=1 then begin inc(tail); f[tail].x:=xx; f[tail].y:=yy; f[tail].z:=f[head].z+1; a[xx,yy]:=0; end; end; end; inc(sum); b[sum]:=f[head].z; end; begin assign(input,'graph.in'); assign(output,'graph.out'); reset(input); rewrite(output); init; for i:=1 to n do for j:=1 to n do if a[j,i]=1 then bfs(j,i); sort(1,sum); writeln(sum); for i:=1 to sum do writeln(b[i]); close(input); close(output); end.