北大ACM 1009题—Edge Detection

Edge Detection
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 15307   Accepted: 3445

Description

IONU Satellite Imaging, Inc. records and stores very large images using run length encoding. You are to write a program that reads a compressed image, finds the edges in the image, as described below, and outputs another compressed image of the detected edges. 
A simple edge detection algorithm sets an output pixel's value to be the maximum absolute value of the differences between it and all its surrounding pixels in the input image. Consider the input image below: 

The upper left pixel in the output image is the maximum of the values |15-15|,|15-100|, and |15-100|, which is 85. The pixel in the 4th row, 2nd column is computed as the maximum of |175-100|, |175-100|, |175-100|, |175-175|, |175-25|, |175-175|,|175-175|, and |175-25|, which is 150. 
Images contain 2 to 1,000,000,000 (109) pixels. All images are encoded using run length encoding (RLE). This is a sequence of pairs, containing pixel value (0-255) and run length (1-109). Input images have at most 1,000 of these pairs. Successive pairs have different pixel values. All lines in an image contain the same number of pixels. 

Input

Input consists of information for one or more images. Each image starts with the width, in pixels, of each image line. This is followed by the RLE pairs, one pair per line. A line with 0 0 indicates the end of the data for that image. An image width of 0 indicates there are no more images to process. The first image in the example input encodes the 5x7 input image above. 

Output

Output is a series of edge-detected images, in the same format as the input images, except that there may be more than 1,000 RLE pairs. 

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

Hint

A brute force solution that attempts to compute an output value for every individual pixel will likely fail due to space or time constraints. 

Source

/*
*突破点在于Input的pair,pair上限只有1000,数据量是最少的,因此只能利用这点去解题。
*要利用pair,就必须懂得“跳跃式编码”,就是说只在像素发生变化的位置进行编码,
*而像素没有变化的位置则其编码值与其左边的像素一致。
*/

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;

const int size=1000;  //每幅图片的pair上限
int width;  //Map的宽
int total=0;  //像素点总个数

typedef class OutMapPix
{
	public:
		int pos;    //OutMap中每个像素点的顺序位置,pos从1开始
		int code;   //OutMap中每个像素点对应InMap的编码
}Pix;

int InMapPair[size][2];  //InMapPair[][0]为像素值,InMapPair[][1]为InMapPair[][0]连续出现的个数
Pix OutMap[size*8];    //每个pix都依赖其周围的8个点编码

int cmp(const void* a,const void* b);  //快排比较规则
int GetValue(int pos);  //返回第pos个像素点的像素值
int GetCode(int pos);   //返回第pos个像素点的编码

int main(int k)
{
	while(cin>>width && width)
	{
		int pairv,pairt;
		k=total=0;
		while(cin>>pairv>>pairt && pairt)
		{
			InMapPair[k][0]=pairv;
			InMapPair[k++][1]=pairt;
			total+=pairt;
		}
		int PairNum=k;  //pair的个数

		cout<<width<<endl;

		int pos=1;  //当前处理的像素点的位置
		k=0; //OutMap[]指针
		for(int p=0;p<=PairNum;p++)
		{
			int row=(pos-1)/width;  //得到pos在二维图对应的坐标
			int col=(pos-1)%width;

			for(int i=row-1;i<=row+1;i++)        //枚举(row,col)周围及其自身共9个点(x,y)
				for(int j=col-1;j<=col+1;j++)
				{
					int tpos=i*width+j;  //得到(x,y)的顺序位置

					if(i<0 || j<0 || j>=width || tpos>=total)
						continue;

					OutMap[k].pos=tpos+1;
					OutMap[k++].code=GetCode(tpos+1);  //对发生变化的像素点的附近8个点编码
				}

			pos+=InMapPair[p][1];  //跳跃,确定下一个像素发生变化的点的位置
		}

		qsort(OutMap,k,sizeof(Pix),cmp);  //对OutMap根据顺序位置

		/*OutPut*/

		Pix temp=OutMap[0];
		for(int i=0;i<k;i++)
		{
			if(temp.code==OutMap[i].code)
				continue;
			cout<<temp.code<<' '<<OutMap[i].pos-temp.pos<<endl;
			temp=OutMap[i];
		}
		cout<<temp.code<<' '<<total-temp.pos+1<<endl;
		cout<<"0 0"<<endl;

	}
	cout<<0<<endl;

	return 0;
}


/*快排比较规则*/
int cmp(const void* a,const void* b)
{
	Pix* x=(Pix*)a;
	Pix* y=(Pix*)b;
	return x->pos - y->pos;
}

/*返回第pos个像素点的像素值*/
int GetValue(int pos)
{
	int i=0,p=0;
	while(p<pos)
		p+=InMapPair[i++][1];

	return InMapPair[i-1][0];
}

/*返回第pos个像素点的编码*/
int GetCode(int pos)
{
	int code=GetValue(pos);
	int MaxAbs=0;

	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;

			if(i<0 || j<0 || j>=width || tpos>=total || tpos==pos-1)  //tpos==pos-1为中心的像素点,即当前待编码的点
				continue;

			int tcode=GetValue(tpos+1);

			if(MaxAbs<abs(tcode-code))   //注意取绝对值
				MaxAbs=abs(tcode-code);
		}
	return MaxAbs;
}


posted @ 2013-06-14 19:53  Finlay Liu  阅读(431)  评论(0编辑  收藏  举报