Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 21730 | Accepted: 5099 |
Description
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 (10 9) 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-10 9). 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
Output
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
看到这一题后我唯一的思路就是暴力求解,但暴力求解显然是行不通的,因为图像最多会有10亿个像素,把他们全部存储下来会超内存,运行起来也会TLE,题目中的Hint也告诉我们不要暴力求解。之后上网看了几篇博客,发现大家使用的方法叫做“跳跃式编码”,首先存储时不是把所有的像素都存储下来,而是只存储输入的数据,即像素值和值出现的次数,其次我们先假设像素是线性排列,给每一个像素编号依次编号,然后根据编号和题目输入给出的width求出其在二维数组(即图像)中的行和列,具体的方法如下:
(1)找出每一次像素发生变化的位置posInLine,举个例子假如像素值为0 ,0 , 0, 1 ,1 ,1则变化的位置为第一个0的位置0和第一个1的位置3,将变化的位置转化为二维数组中的行row和列col;
(2)求出(row,col)及其周围共9个点的像素值编码code与位置pos,求解方法题目中已给出,并存储下来,我的代码中存在了vector类型的result中;
(3)找出下一个像素发生变化的位置,即把当前变化的位置加上当前值的个数,重复(2)直至所有的输入对都处理完成;
(4)按pos从小到大对result进行排序后输出。
这里还有一点需要注意,比如我使用vector来存储输入的数据,假设输入的数据为:
7
15 4
100 15
25 2
175 2
25 5
175 2
25 5
0 0
则共输入了7对数据,我们将这7组数据输入之后还要在数组的最后加上"0 1"这一组数据,可以配合这样一组输入数据来理解:
输入:
30
10 41
20 41
15 41
30 41
25 41
0 5
0 0
0
输出应为:
30
0 10
10 62
5 20
15 62
5 20
25 6
5 15
0 9
25 6
0 0
0
我就是因为这个问题卡了很久。
具体代码如下:
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
struct Pair
{
int value; //输入的值
int times; //value的个数
Pair(int v, int t) :value(v), times(t) {}
};
struct Result
{
int code; //编码
int pos; //code的个数
Result(int c, int p) :code(c), pos(p) {}
};
bool cmp(Result r1, Result r2) //将result按pos从小到大排序
{
return r1.pos<r2.pos;
}
vector<Pair> pairs;
vector<Result> result;
int width = 0;
int total = 0; //像素的总个数
int getValue(int pos) //获得pos位置的像素值
{
int p = 0, i = 0;
while (p<=pos)
p += pairs[i++].times;
return pairs[--i].value;
}
int encode(int row, int col) //编码函数
{
int posInLine = row*width + col;
int centerValue = getValue(posInLine);
int maxValue = 0;
for (int i = row - 1;i <= row + 1;i++)
for (int j = col - 1;j <= col + 1;j++)
{
int pos = i*width + j;
if (i<0 || j<0 || j>=width || pos == posInLine || pos >= total)
continue;
int arroundValue = getValue(pos);
int value = abs(centerValue - arroundValue);
maxValue = value>maxValue ? value : maxValue;
}
return maxValue;
}
int main()
{
//freopen("test.txt", "r", stdin);
while (scanf("%d", &width) == 1 && width)
{
pairs.clear();
result.clear();
total = 0;
printf("%d\n", width);
int value, times;
while (scanf("%d%d", &value, ×) && (value||times)) //输入数据
{
pairs.push_back(Pair(value, times));
total += times;
}
pairs.push_back(Pair(0, 1)); //这一步尤其注意
for (int i = 0;i<pairs.size();i++) //遍历vector,如果使用普通数组存储,则不应使用<,而应该<=
{
int row = curPos / width;
int col = curPos % width;
for (int j = row - 1;j <= row + 1;j++)
for (int k = col - 1;k <= col + 1;k++)
{
int posInLine = j*width + k; //获取行为j,列为k的像素编号
if (j<0 || k<0 || k >= width || posInLine >= total)
continue;
int code = encode(j, k);
result.push_back(Result(code, posInLine)); //将编码后的像素存入result
}
curPos += pairs[i].times; //跳到下一个像素变化点
}
sort(result.begin(), result.end(), cmp); //将result按pos从小到大排序
/*for (int i = 0;i < result.size();i++)
cout << result[i].code << " " << result[i].pos << endl;*/
Result cur = result[0]; //输出
for (int i = 0;i<result.size();i++)
{
if (cur.code == result[i].code)
continue;
printf("%d %d\n", cur.code, result[i].pos - cur.pos);
cur = result[i];
}
printf("%d %d\n", cur.code, total - cur.pos);
printf("0 0\n");
}
printf("0\n"); //注意最后输出0
return 0;
}