[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.
View Code

posted on 2015-11-02 16:16  川汉唐  阅读(378)  评论(0编辑  收藏  举报

导航