POJ 1009 Edge Detection(图像边缘检测)

来源:互联网 发布:淘宝账号怎么买 编辑:程序博客网 时间:2024/05/20 14:23

Description
给出一张数字图,对于每个像素点求出这个点与其周围所有点差的绝对值的最大值
这里写图片描述
Input
多组输入,每组数据第一行为一个整数n(n<=1000),表示图的宽度,接下来每行两个整数a,b(a<=255,b<=10^9),分别表示此段数字大小和长度,每组数据以0 0结束,n=0时结束输入
Output
对于每组输入,在求出每个像素点与其周围点差的绝对值后按输入格式输出,即第一行为n,中间为每个数字连续段的数值和长度,以0 0结束每组输出,以0结束全部输出
Sample Input
7
15 4
100 15
25 2
175 2
25 5
175 2
25 5
0 0
10
35 500000000
200 500000000
0 0
3
255 1
10 1
255 2
10 1
255 2
10 1
255 1
0 0
0
Sample Output
7
85 5
0 2
85 5
75 10
150 2
75 3
0 2
150 2
0 4
0 0
10
0 499999990
165 20
0 499999990
0 0
3
245 9
0 0
0
Solution
首先暴力必挂QAQ
然后从答案可以看出肯定会有一些连续段答案相同,所以思路就是,先找出在原图的某一连续段中,答案值可能改变的几个像素(做标记),再一次次跳跃到这几个像素中计算它们的答案值,但是问题是,怎么样的像素才是需要计算的像素。
这里写图片描述
如上图一个map,紫色标注的都是要标记的格子,红色边框的代表这一个连续段的起始格。我们可以发现,每个连续段的起始格,都是要标记的格子,同时,每个要标记的格子,都是一个连续段起始格的周围8个格子中的一个。所以,只需要一个个枚举每个连续段的起始格,并计算它和它四周8个格子的答案值,最后统计答案的时候按照位置先后排序,答案中相同的连续段就合并。因为最多只有1000个连续段,所以不管是时间还是空间都不会超。
这里写图片描述
Code

#include<cstdio>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>#include<functional>using namespace std;#define size 1005struct pix{    int pos;//pos表示这个像素点的位置     int code;//code表示这个像素点的答案值 }outmap[size*8];int inmap[size][2];//inmap[][0]表示这个连续段的数值,inmap[][1]表示这个连续段的长度 int width,cntp,tot;//width为图宽度,cntp为图中连续段段数,tot为图中像素点总个数 int cmp(pix x,pix y)//排序函数,对pos升序排 {    return x.pos<y.pos;}int getnum(int pos)//返回原图上pos位置上的数值 {    int p=0,i=0;    while(p<pos)        p+=inmap[i++][1];    return inmap[i-1][0];}int getcode(int pos)//计算pos位置上的答案 {    int num=getnum(pos),ret=0;    int row=(pos-1)/width;//pos所处排数     int col=(pos-1)%width;//pos所处列数     for(int i=row-1;i<=row+1;i++)//枚举pos周围八个方向         for(int j=col-1;j<=col+1;j++)        {            int tpos=i*width+j;            if(i<0||j>=width||j<0||tpos==pos-1||tpos>=tot)                continue;            int temp=getnum(tpos+1);            if(ret<abs(temp-num))                ret=abs(temp-num);        }    return ret;}int main(){    while(scanf("%d",&width)&width>0)    {        int num,len;        cntp=tot=0;//初始化         while(scanf("%d%d",&num,&len)&&len>0)        {            inmap[cntp][0]=num;            inmap[cntp++][1]=len;            tot+=len;        }        printf("%d\n",width);//按格式输出         int pos=1,k=0;        for(int p=0;p<=cntp;p++)//枚举每个连续段         {            int row=(pos-1)/width;//每个连续段起始点所处行数             int col=(pos-1)%width;//每个连续段起始点所处列数             for(int i=row-1;i<=row+1;i++)//枚举起始点周围八个点                 for(int j=col-1;j<=col+1;j++)                {                    int tpos=i*width+j;//此处tpos其实是真实tpos标号减一                     if(i<0||j<0||j>=width||tpos>=tot)//超出图范围舍去                         continue;                    outmap[k].pos=tpos+1;                    outmap[k++].code=getcode(tpos+1);                }            pos+=inmap[p][1];//跳跃到下一连续段起始点         }        sort(outmap,outmap+k,cmp);//对答案按pos升序排序         pix temp=outmap[0];        for(int i=0;i<k;i++)        {            if(outmap[i].code==temp.code)//连续则不输出                 continue;            printf("%d %d\n",temp.code,outmap[i].pos-temp.pos);            temp=outmap[i];        }        printf("%d %d\n",temp.code,tot-temp.pos+1);//最后一部分         printf("0 0\n");//按格式输出     }    printf("0\n");//按格式输出     return 0;   }
0 0
原创粉丝点击