POJ 1009: Edge Detection
来源:互联网 发布:中国网络购物发展现状 编辑:程序博客网 时间:2024/05/16 19:53
解题要点: 想清楚输出图像 RLE 编码的各个数据头可能出现的位置.
对输出图像的每个像素都进行计算是不切实际的, 因为时间复杂度太高. 对 RLE 编码进行解码也是不切实际的, 因为空间复杂度太高. 唯一的解决办法, 只有想清楚输出图像 RLE 编码的各个数据头可能出现的位置, 然后仅对这些可能位置进行计算.
事实上, 若设 p 为输入图像的任一数据头在图像中的位置, 则除了左上角和左下角之外, 输出图像的其余数据头都只可能出现在下列 8 个位置之中:
- p - width - 1, p - width, p - width + 1,
- p - 1, p + 1,
- p + width - 1, p + width, p + width + 1.
上述结论证明起来并不麻烦, 画几个图就可以弄清楚. 破解了这个关窍之后, 这道题也就不神秘了.
编程时, 可考虑在输入图像的后部增加一个扩充像素, 其坐标为 width * height, 其值等于 width * height - 1 处的像素值. 这样做可以使左下角不再具有特殊性, 并且有利于程序中的一些循环结构的实现. 对于输出图像, 也可以做相似的处理.
代码如下:
代码中有一些注释掉的内容, 注释掉的原因是其对于本题目无用. 如果对这些内容进行反注释, 则代码中的 Image 类会具有更强的鲁棒性, 从而成为一个实用的类.
#include <iostream>#include <set>#include <cmath>#include <algorithm>using namespace std;typedef pair<long, int> Rle;const int& ( *iMax )( const int&, const int& ) = max<int>;class Image { protected:// bool bFinished; // 此锁定机制能够提升鲁棒性, 在本题目中无用. set<Rle> src; set<Rle> dst; int width; long length; int getVal( const long& pixelPos, set<Rle>::const_iterator& relPos ) const; void calcPixel( const long& pixelPos, set<Rle>::const_iterator relPos ); void edgeDetect(); public: Image( const int& width_ ); void push( const int& val, const long& len ); void finish(); void print();};Image::Image( const int& width_ ) : width( width_ ), length( 0 )/*, bFinished( false )*/ {}void Image::push( const int& val, const long& len ) {// if( bFinished ) {// return;// } src.insert( Rle( length, val ) ); length += len;}int Image::getVal( const long& pixelPos, set<Rle>::const_iterator& relPos ) const { if( relPos->first <= pixelPos ) { while( relPos->first < pixelPos ) { ++relPos; } if( relPos->first > pixelPos ) { --relPos; } } else { do { --relPos; } while( relPos->first > pixelPos ); } return relPos->second;}void Image::calcPixel( const long& pixelPos, set<Rle>::const_iterator relPos ) { if( pixelPos < 0 || pixelPos >= length ) { return; } const int val = getVal( pixelPos, relPos ); int dstVal = 0; long tmpPos; tmpPos = pixelPos - width - 1; // 左上 if( tmpPos >= 0 && tmpPos % width != width - 1 ) { dstVal = iMax( abs( getVal( tmpPos, relPos ) - val ), dstVal ); } ++tmpPos; // 上 if( tmpPos >= 0 ) { dstVal = iMax( abs( getVal( tmpPos, relPos ) - val ), dstVal ); } ++tmpPos; // 右上 if( tmpPos > 0 && tmpPos % width != 0 ) { dstVal = iMax( abs( getVal( tmpPos, relPos ) - val ), dstVal ); } tmpPos = pixelPos - 1; // 左 if( tmpPos >= 0 && tmpPos % width != width - 1 ) { dstVal = iMax( abs( getVal( tmpPos, relPos ) - val ), dstVal ); } tmpPos += 2; // 右 if( tmpPos < length && tmpPos % width != 0 ) { dstVal = iMax( abs( getVal( tmpPos, relPos ) - val ), dstVal ); } tmpPos = pixelPos + width - 1; // 左下 if( tmpPos < length && tmpPos % width != width - 1 ) { dstVal = iMax( abs( getVal( tmpPos, relPos ) - val ), dstVal ); } ++tmpPos; // 下 if( tmpPos < length ) { dstVal = iMax( abs( getVal( tmpPos, relPos ) - val ), dstVal ); } ++tmpPos; // 右下 if( tmpPos < length && tmpPos % width != 0 ) { dstVal = iMax( abs( getVal( tmpPos, relPos ) - val ), dstVal ); } dst.insert( Rle( pixelPos, dstVal ) );}void Image::edgeDetect() { calcPixel( 0, src.begin() ); // 左上角 for( set<Rle>::const_iterator pos = src.begin(); pos != src.end(); ++pos ) { calcPixel( pos->first - width - 1, pos ); // 左上 calcPixel( pos->first - width, pos ); // 上 calcPixel( pos->first - width + 1, pos ); // 右上 calcPixel( pos->first - 1, pos ); // 左 calcPixel( pos->first + 1, pos ); // 右 calcPixel( pos->first + width - 1, pos ); // 左下 calcPixel( pos->first + width, pos ); // 下 calcPixel( pos->first + width + 1, pos ); // 右下 } dst.insert( Rle( length, -1 ) ); for( set<Rle>::iterator pos = dst.begin(); pos != dst.end(); ++pos ) { set<Rle>::iterator pos2 = pos; ++pos2; while( pos2 != dst.end() ) { if( pos2->second != pos->second ) { break; } set<Rle>::iterator tmp = pos2; ++pos2; dst.erase( tmp ); } }}void Image::finish() {// if( bFinished ) {// return;// } src.insert( Rle( length, src.rbegin()->second ) );// bFinished = true; edgeDetect();}void Image::print() {// if( !bFinished ) {// return;// } cout << width << endl; set<Rle>::const_iterator pos = dst.begin(); set<Rle>::const_iterator pos2 = pos; ++pos2; for( ; pos2 != dst.end(); ++pos, ++pos2 ) { cout << pos->second << " " << pos2->first - pos->first << endl; } cout << "0 0" << endl;}int main() { int width; int val; long len; while( cin >> width && width != 0 ) { Image img( width ); while( cin >> val >> len && ( val != 0 || len != 0 ) ) { img.push( val, len ); } img.finish(); img.print(); } cout << 0 << endl;}
0 0
- POJ 1009 Edge Detection
- poj 1009 Edge Detection
- poj 1009 Edge Detection
- POJ 1009 Edge Detection
- POJ-1009-Edge Detection
- [POJ][1009]Edge Detection
- POJ 1009: Edge Detection
- POJ 1009 Edge Detection
- POJ 1009--Edge Detection
- POJ 1009Edge Detection
- POJ 1009 Edge Detection
- POJ 1009--Edge Detection
- POJ 1009 Edge Detection
- poj 1009 Edge Detection (未完成)
- poj 1009 Edge Detection 模拟
- POJ 1009 Edge Detection 笔记
- POJ 1009 解题报告 Edge Detection
- POJ 1009 Edge Detection解题报告
- c++静态类
- CSS3 Media Queries 简介
- OpenCV.2.Computer.Vision.Application.Programming.Cookbook--Scanning an image with pointers
- github
- 剑指offer :07 用两个栈实现队列
- POJ 1009: Edge Detection
- git使用
- 链式结构实现堆排序
- AngularJs路由继承
- 根据先序序列和中序序列重建二叉树
- 配置MySQL数据库的驱动程序
- c#循环结构(四)----foreach循环
- DDPush开源推送框架源码分析之APPServer到DDPush
- *exec,source和fork的区别*