题目是对RLE压缩的图像进行边缘检测。
RLE是游程编码的意思(Run length edcoding),比如555555根据游程编码可以编码成5 6。在代码中可以用控制符来区分编码字节和重复次数。
题目大意如下:
输入一张或多张游程编码的压缩图片,输出该图片的边缘检测的图片。其中,输入时0表示没有下一张图片,0 0表示本张图片输入结束。
算法思路:
1)输入的为RLE压缩图像,需要将图像还原为bitmap的形式才能计算图像的边缘检测。
缺点:如果图像过大,比如达到了10^9个像素,那么需要创建的二位数组将会超出题目给定内存的限制
优化:建立一个view,大小为3*column,这样每次只用存3行的像素,并且对于中间的一行,上下文都是可见的,因此可以做到逐行解析,逐行处理
2)根据上面的改进方法,无论多大的图像只要时间足够,都是可以计算出边缘检测图形的,但是也有缺点
缺点:逐行处理所花的时间会随着图像的增大而变多,当图形足够大的时候,时间会增到到超出限制。如果图像中重复单元很多,存在很大的优化空间。
优化:检测输入的像素,如果输入的重复像素过多,可以计算出有多少像素的边缘检测值是一样的,那么可以省去这些像素的计算
整体代码如下:
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException, InvalidInputException {
BufferedReader stdin =
new BufferedReader(
new InputStreamReader(System.in));
String line = null;
String[] input = null;
while (true) {
line = stdin.readLine();
int width = Integer.parseInt(line);
if (width == 0) break;
int[][] matrix = new int[3][width];
RlePair pair = new RlePair(0, 0);
int value = 0;
int times = 0;
int index = 0;
int delta = 0;
int diffValue = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < width; j++) {
matrix[i][j] = -1; // -1 is null
}
}
while (true) {
line = stdin.readLine();
input = line.split("\\s");
if (input.length != 2) {
throw new InvalidInputException();
}
value = Integer.parseInt(input[0]);
times = Integer.parseInt(input[1]);
if (value == 0 && times == 0) break;
int currRow = 0;
//-----------------------------------------------------------------
// 算法主体
for (int n = 0; n < times; n++) {
currRow = (index + n) / width + 1 - delta;
if (currRow == 3) {
for (int i = 0; i < width; i++) {
if (matrix[1][i] == -1) break;
diffValue = max(width, matrix, i);
if (diffValue == pair.value) {
pair.times++;
} else {
if (pair.times != 0) System.out.println(pair.toString());
pair = new RlePair(diffValue, 1);
}
}
delta++;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < width; j++) {
matrix[i][j] = matrix[i + 1][j];
}
}
currRow = (index + n) / width + 1 - delta;
if (n / width > 2 && (times - n) / width > 1) {
int d = (times - n) / width - 1;
pair.times += d * width;
n += d * width;
delta += d;
}
}
matrix[currRow][(index + n) % width] = value;
}
index += times;
}
// 算法主体
//-----------------------------------------------------------------
// 最后几行的处理
for (int i = 0; i < width; i++) {
if (matrix[1][i] == -1) break;
diffValue = max(width, matrix, i);
if (diffValue == pair.value) {
pair.times++;
} else {
if (pair.times != 0) System.out.println(pair.toString());
pair = new RlePair(diffValue, 1);
}
}
for (int i = 0; i < 2; i++) {
for (int j = 0; j < width; j++) {
matrix[i][j] = matrix[i + 1][j];
}
}
for (int j = 0; j < width; j++) {
matrix[2][j] = -1;
}
for (int i = 0; i < width; i++) {
if (matrix[1][i] == -1) break;
diffValue = max(width, matrix, i);
if (diffValue == pair.value) {
pair.times++;
} else {
if (pair.times != 0) System.out.println(pair.toString());
pair = new RlePair(diffValue, 1);
}
}
System.out.println(pair.toString());
System.out.println("0 0");
// 最后几行的处理
//-----------------------------------------------------------------
}
if (stdin != null) {
stdin.close();
stdin = null;
}
}
private static int max(int width, int[][] matrix, int index) {
// TODO Auto-generated method stub
// 0: 0 1 2
// 1: 3 4
// 2: 5 6 7
int[] x = new int[] {-1, -1, -1, -1, -1, -1, -1, -1}; // 8
if (index - 1 >= 0) {
x[0] = matrix[0][index - 1];
x[3] = matrix[1][index - 1];
x[5] = matrix[2][index - 1];
}
x[1] = matrix[0][index];
x[6] = matrix[2][index];
if (index + 1 < width) {
x[2] = matrix[0][index + 1];
x[4] = matrix[1][index + 1];
x[7] = matrix[2][index + 1];
}
int maxDiff = 0;
for (int n : x) {
if (n != -1) {
maxDiff = maxDiff > Math.abs(matrix[1][index] - n) ? maxDiff : Math.abs(matrix[1][index] - n);
}
}
return maxDiff;
}
}
class RlePair {
int value;
int times;
public RlePair(int value, int times) {
this.value = value;
this.times = times;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.value + " " + this.times;
}
}
@SuppressWarnings("serial")
class InvalidInputException extends Exception {
}
让我郁闷的是,代码提交poj一直是runtime error,而自己测试确没什么问题。我测试的环境是jdk7.0,不知道和jdk升级是否有关系。。。(狡辩一下:我练习的目标是训练自己思考算法的感觉的,此题的目的已经达到,如果poj能多给一点错误信息我是很乐意让这道题accept的:))
分享到:
相关推荐
【压缩包子文件的文件名称列表】:"POJ1009-Edge Detection.cpp"、"POJ1009-Edge Detection.doc" "POJ1009-Edge Detection.cpp"是解决该问题的C++源代码文件,很可能包含了实现边缘检测算法的函数和主程序逻辑。...
通过阅读和分析poj_1699.txt文件,我们可以学习到如何分析问题、设计算法、编写代码以及验证解决方案的正确性,这对于提高编程和算法能力非常有帮助。同时,这也是一个很好的实例,展示了在面对实际问题时,如何运用...
标签"poj poj_27 poj27 poj2775"进一步确认了这是一道关于POJ平台的编程挑战,其中"poj_27"可能是表示第27类问题或者某种分类,而"poj27"可能是对"poj2775"的简写。 压缩文件中的"www.pudn.com.txt"可能是一个链接...
标题中的"poj_2682(3).rar"是一个指向编程竞赛问题的引用,通常这类问题在网站如POJ(Programming Online Judge)上出现,供程序员解决并提交代码进行测试。这个问题的编号是2682,可能涉及到特定的数据结构或算法...
poj1009 Edge Detection 可以直接AC的
标题"Poj_1102_.rar_poj11"暗示了这是一个关于解决Poj_1102问题的资源包,通常在编程竞赛或在线判题系统如POJ(Problem Set of Judge Online)上遇到。POJ是中国的一个在线编程训练平台,提供了各种算法题目供用户...
标题中的“POJ_3131.zip_POJ 八数码_poj”指的是一个与编程竞赛网站POJ(Problem Set Algorithm)相关的项目,具体是针对3131号问题的解决方案,该问题涉及到了八数码游戏。八数码游戏,又称滑动拼图,是一个经典的...
2遍dp poj_3613解题报告 poj_3613解题报告
【标题】"poj_3310.rar_3310_poj"是一个与编程竞赛相关的压缩包,其中包含了对POJ(Problem Online Judge)3310问题的解决方案和详细解析。POJ是一个著名的在线编程竞赛平台,提供各种算法题目供参赛者练习和提交...
标题 "ACM.zip_ACM_poj_poj3187_poj3669" 提供的信息表明,这个压缩包包含的是与ACM(国际大学生程序设计竞赛)相关的编程题目解决方案,具体是POJ(Programming Online Judge)平台上的两道题目,编号分别为poj3187...
《POJ 1010 Stamps:解题思路与陷阱分析》 POJ 1010,也被称为“邮票问题”,是编程竞赛中的一道经典题目,旨在考察参赛者的动态规划和数学思维能力。这个题目在编程爱好者中具有较高的知名度,因为它涉及到有趣的...
标题中的“pku_poj_2187.rar_poj 2187_凸包问题”表明这是一个关于北京大学(Peking University, PKU)编程竞赛平台POJ上的第2187题,题目主要涉及凸包问题。描述中的“O(nlogn)凸包问题 poj2187”提示我们解决这个...
【标题】"poj_1002_487.rar_poj 1002"指的是北京大学在线编程平台上的第1002道题目,这道题目涉及到计算机科学中的算法设计与实现,特别是字符串处理和哈希映射。在这个问题中,我们需要编写一个程序,该程序能够...
标题中的“POJ3277.rar_3277 poj_poj3277_多个面积_线段树”是指一个与编程竞赛相关的压缩文件,特别提到了POJ(Problemset Online Judge)的第3277号问题。POJ是一个著名的在线编程竞赛平台,参与者需要解决各种...
C_(POJ_1854)(分治).cpp
《POJ 1990:树状数组解题策略详解》 在编程竞赛的世界里,POJ(Programming Online Judge)是一个备受瞩目的在线评测系统,它提供了丰富的编程题目供参赛者挑战。其中,编号为1990的题目是一道涉及数据结构与算法...
标题中的"jihe.rar_2289_POJ 3714_poj3714_poj3714 Ra_visual c" 提到了一个压缩文件,可能包含有关编程竞赛或算法解决的资源,特别是与POJ(Problem On Judge)平台上的问题3714相关的。"Ra_visual c"可能指的是...
D_(POJ_1723)(思维)(sort).cpp
D_(POJ_1723)(思维)(第k大数).cpp
现在,让我们逐个分析压缩包中的文件名,尽管没有提供具体的题目和代码细节,但我们可以基于常见的POJ题目类型推测可能涉及的知识点: 1. 13295.cpp:可能是一个关于排序或查找的问题,因为这类问题在编程竞赛中很...