Edge Detection
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 22835   Accepted: 5398

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

 
分析:
英文的题目,有点蛋疼,有几个限制数字理解错了意思,浪费了时间。
注意点:
1. 计算点不是上下左右4个点,而是周围8个点。
2. 每个点与左侧delta是前一个点与右侧的delta,不需要重复计算。
3. 行可以很长很长,注意long。
4. 每组input可以长为1000,而不是256。
5. 处理采用输入一组处理一组,循环处理。
6. 需要采用快进处理:1)多行相同;2)同一行相同数字很多。(考虑了最简单场景)
 
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 #define MAX_POINT_SERIES_NUM 1000
  6 
  7 #define FAILURE (int)0xF
  8 #define SUCCESS (int)0x0
  9 
 10 #define TRUE  (int)1
 11 #define FALSE (int)0
 12 
 13 #define MIN(a, b) (((a) < (b))?(a):(b))
 14 #define MAX(a, b) (((a) > (b))?(a):(b))
 15 
 16 typedef int BOOL;
 17 
 18 typedef struct
 19 {
 20     int value;
 21     long long num;
 22     long long startIdx;
 23     long long endIdx;
 24 }PointSeries;
 25 
 26 typedef struct
 27 {
 28     long long imageWide;
 29     int pointsNum;
 30     long long endIdx;
 31     PointSeries points[MAX_POINT_SERIES_NUM];
 32 }Image;
 33 
 34 Image g_input;
 35 Image g_output;
 36 
 37 int GetInputImage(Image *input)
 38 {
 39     int i = 0;
 40     long long idx = 0;
 41     PointSeries *points = NULL;
 42 
 43     scanf("%I64d", &input->imageWide);
 44     if(0 == input->imageWide)
 45     {
 46         printf("0\n");
 47         return FAILURE;
 48     }
 49 
 50     do
 51     {
 52         points = &input->points[i];
 53         scanf("%d %I64d", &points->value, &points->num);
 54         points->startIdx = idx;
 55         points->endIdx = idx + points->num - 1;
 56         idx = idx + points->num;
 57         i++;
 58     }while(points->num != 0 && MAX_POINT_SERIES_NUM <= i);
 59 
 60     input->endIdx = input->points[i-1].endIdx;
 61 
 62     input->pointsNum = i;
 63     return SUCCESS;
 64 }
 65 
 66 void PrintImage(Image *image)
 67 {
 68     int i;
 69     printf("%I64d\n", image->imageWide);
 70     for(i = 0; i < image->pointsNum; i++)
 71     {
 72         printf("%d %I64d\n",
 73                image->points[i].value,
 74                image->points[i].num);
 75     }
 76     if(image->imageWide != 0) printf("0 0\n");
 77 }
 78 
 79 static int GetLeftDelta(long long wide, PointSeries *points, long long idx, PointSeries *cmpPoints)
 80 {
 81     PointSeries *lastPoints = NULL;
 82     long long lastIdx = idx - 1;
 83 
 84     if(idx % wide != 0
 85        && lastIdx >= 0
 86        && lastIdx < points->startIdx)
 87     {
 88         lastPoints = points-1;
 89         return abs(lastPoints->value - cmpPoints->value);
 90     }
 91 
 92     return 0;
 93 }
 94 
 95 static int GetRightDelta(Image *input, PointSeries *points, long long idx, PointSeries *cmpPoints)
 96 {
 97     PointSeries *nextPoints = NULL;
 98     long long nextIdx = idx + 1;
 99 
100     if(idx % input->imageWide != input->imageWide - 1
101        && points->endIdx < input->endIdx
102        && nextIdx > points->endIdx)
103     {
104         nextPoints = points+1;
105         return abs(nextPoints->value - cmpPoints->value);
106     }
107 
108     return 0;
109 }
110 
111 static int GetPointSeries(long long idx, long long endIdx, PointSeries **targetPoints)
112 {
113     PointSeries *points = (*targetPoints);
114     if(idx < 0 || idx > endIdx) return FAILURE;
115 
116     while(1)
117     {
118         if(idx <= points->endIdx && points->startIdx <= idx) break;
119 
120         if(idx > points->endIdx)
121         {
122             points++;
123         }
124         else if(idx < points->startIdx)
125         {
126             points--;
127         }
128     }
129 
130     *targetPoints = points;
131 
132     return SUCCESS;
133 }
134 
135 static int GetOtherLineDelta(Image *input, PointSeries *orgPoints, long long idx)
136 {
137     int leftDelta, rightDelta, delta;
138     PointSeries *target = orgPoints;
139 
140     if(FAILURE == GetPointSeries(idx, input->endIdx, &target)) return 0;
141 
142     leftDelta = GetLeftDelta(input->imageWide, target, idx, orgPoints);
143     rightDelta = GetRightDelta(input, target, idx, orgPoints);
144     delta = abs(target->value - orgPoints->value);
145 
146     delta = MAX(delta , leftDelta);
147     delta = MAX(delta , rightDelta);
148 
149     return delta;
150 }
151 
152 void SaveOutput(Image *output, int delta, long long num)
153 {
154     PointSeries *points = &output->points[output->pointsNum];
155 
156     if(num == 0) return;
157 
158     if(output->pointsNum == 0)
159     {
160         points->num = num;
161         points->value = delta;
162         output->pointsNum = 1;
163         return;
164     }
165 
166     if((points-1)->value != delta)
167     {
168         points->num = num;
169         points->value = delta;
170         output->pointsNum++;
171     }
172     else
173     {
174         (points-1)->num += num;
175     }
176 }
177 
178 void ProcPoints(Image *input, PointSeries *points, long long num, int *rightDelta, long long *idx, Image *output)
179 {
180     long long j;
181     long long tmpIdx = *idx;
182     int leftDelta, upDelta, dowmDelta, delta;
183     int tmpRight = *rightDelta;
184 
185     for(j = 0; j < num; j++)
186     {
187         leftDelta = tmpRight;
188         tmpRight = GetRightDelta(input, points, tmpIdx, points);
189         upDelta = GetOtherLineDelta(input, points, tmpIdx - input->imageWide);
190         dowmDelta = GetOtherLineDelta(input, points, tmpIdx + input->imageWide);
191         delta = MAX(leftDelta, tmpRight);
192         delta = MAX(delta, upDelta);
193         delta = MAX(delta, dowmDelta);
194         SaveOutput(output, delta, 1);
195         tmpIdx++;
196     }
197     *idx = tmpIdx;
198     *rightDelta = tmpRight;
199 }
200 
201 void RowFastForward(Image *input, PointSeries *points, int *rightDelta, long long *idx, Image *output)
202 {
203     long long firstNum, secondNum, thridNum;
204     long long endIdx;
205     long long wide = input->imageWide;
206 
207     if(*idx % wide == 0)
208         firstNum = wide;
209     else
210         firstNum = wide + 1;
211 
212     ProcPoints(input, points, firstNum, rightDelta, idx, output);
213 
214     if(points->endIdx % wide == wide - 1)
215         endIdx = points->endIdx - wide;
216     else
217         endIdx = points->endIdx - wide - 1;
218 
219     secondNum = endIdx + 1 - points->startIdx - firstNum;
220     thridNum = points->endIdx - endIdx;
221 
222     SaveOutput(output, 0, secondNum);
223     *idx += secondNum;
224 
225     ProcPoints(input, points, thridNum, rightDelta, idx, output);
226 }
227 
228 inline BOOL CanBeRowFastForward(long long pointsNum, long long imageWide)
229 {
230     if(pointsNum >= 4 * imageWide - 1)
231     {
232         return TRUE;
233     }
234     else
235     {
236         return FALSE;
237     }
238 }
239 
240 inline BOOL CanBeSpecFastForward(PointSeries *points, long long wide)
241 {
242     if(points->num == 0
243        || points->num / wide == 0
244        || points->num % wide != 0
245        || (points+1)->num % wide != 0)
246     {
247         return FALSE;
248     }
249     return TRUE;
250 }
251 
252 void SpecFastForward(PointSeries *points, long long wide, int *specDelta, Image *output)
253 {
254     int tmpDeta = *specDelta;
255     long long num, lineNum = points->num / wide;
256 
257     num = (lineNum > 1) ? wide : 0;
258 
259     SaveOutput(output, tmpDeta, num);
260 
261     num = (lineNum > 2) ? ((lineNum - 2)*wide) : 0;
262 
263     SaveOutput(output, 0, num);
264 
265     if((points+1)->num != 0 && lineNum == 1)
266     {
267         tmpDeta = MAX(abs(points->value - (points+1)->value), tmpDeta);
268     }
269     else if((points+1)->num != 0 && lineNum > 1)
270     {
271         tmpDeta = abs(points->value - (points+1)->value);
272     }
273     else if((points+1)->num == 0 && lineNum > 1)
274     {
275         tmpDeta = 0;
276     }
277 
278     SaveOutput(output, tmpDeta, wide);
279 
280     *specDelta = tmpDeta;
281 }
282 
283 void ProcImage(Image *input, Image *output)
284 {
285     long long i = 0, idx = 0;
286     int rightDelta = 0;
287     int specDelta = 0;
288     PointSeries *points = &input->points[0];
289 
290     if(input->pointsNum == 0) return;
291 
292     while(CanBeSpecFastForward(points, input->imageWide))
293     {
294         SpecFastForward(points, input->imageWide, &specDelta, output);
295         points++;
296         i++;
297     }
298 
299     for(; i < input->pointsNum; i++)
300     {
301         points = &input->points[i];
302 
303         if(points->num <= 0) continue;
304 
305         if(CanBeRowFastForward(points->num, input->imageWide))
306         {
307             RowFastForward(input, points, &rightDelta, &idx, output);
308         }
309         else
310         {
311             ProcPoints(input, points, points->num, &rightDelta, &idx, output);
312         }
313     }
314 }
315 
316 inline void InitOutputBuf(Image *input, Image *output)
317 {
318     output->pointsNum = 0;
319     output->imageWide = input->imageWide;
320 }
321 
322 int main()
323 {
324     while(SUCCESS == GetInputImage(&g_input))
325     {
326         InitOutputBuf(&g_input, &g_output);
327         ProcImage(&g_input, &g_output);
328         PrintImage(&g_output);
329     }
330 
331     return 0;
332 }
View Code