| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
Re:做题总结以及注意事项In Reply To:做题总结以及注意事项 Posted by:ixor at 2011-03-24 21:02:50 //g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3
//by ixor( linuxboy_007@hotmail.com )
//简洁起见,使用了一些stl容器,且函数分地较细,
//所以速度并没有完全发挥出来,这方面的优化做的
//不足,仅供参考。
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <list>
#include <vector>
#include <algorithm>
using namespace std;
typedef int PixelVal;
typedef struct RLE_TAG{
PixelVal val;
size_t cnt;
RLE_TAG( int val_a, int cnt_a ):val( val_a ), cnt( cnt_a ) {}
} RleElement;
typedef vector<RleElement> Row;
typedef vector<RleElement> Res;
inline void printRow( const Row &row ){
Row::const_iterator iter;
for( iter = row.begin(); iter != row.end(); iter ++ ){
printf( "(%d,%d)\t", iter->val, iter->cnt );
}
printf( "\n" );
}
inline bool getRow( Row &row, const int & width, Res &res ){
typedef enum SpeedUp_Tag{
PENDING,
READY,
GO
} SpeedUp;
static SpeedUp state = PENDING;
static PixelVal val = -1;
static size_t runLen = 0;
static size_t zeroCnt = 0;
row.clear();
switch( state ){
case PENDING:
break;
case READY:
state = GO;
break;
case GO:
res.push_back( RleElement( 0, zeroCnt ) );
zeroCnt = 0;
state = PENDING;
break;
default:
assert( false );
break;
}
if( !runLen ){
fscanf( stdin, "%d %d", &val, &runLen );
if( !val && !runLen )
return false;
}
int loadLen = 0;
int readCnt = 0;
while( loadLen != width ){
if( runLen >= width - loadLen ){
readCnt = width - loadLen;
row.push_back( RleElement( val, readCnt ) );
runLen -= readCnt;
loadLen += readCnt;
}else{
row.push_back( RleElement( val, runLen ) );
loadLen += runLen;
fscanf( stdin, "%d %d", &val, &runLen );
}
}
//printRow( row );
int lines = runLen / width;
if( lines >= 3 ){
assert( state == PENDING );
zeroCnt = ( lines - 2 ) * width;
runLen -= zeroCnt;
state = READY;
}
return true;
}
inline void printResult( Res &res ){
Res::const_iterator iter;
PixelVal curVal = -1;
size_t curCnt = 0;
for( iter = res.begin(); iter != res.end(); iter ++ ){
if( iter->val != curVal ){
if( curVal != -1 ) printf( "%d %d\n", curVal, curCnt );
curVal = iter->val;
curCnt = iter->cnt;
continue;
}
curCnt += iter->cnt;
}
if( curVal != -1 ) printf( "%d %d\n", curVal, curCnt );
}
inline int accessRow( int idx, Row &row ){
Row::const_iterator iter;
int curIdx;
for( curIdx = 0, iter = row.begin(); iter != row.end(); iter ++ ){
curIdx += iter->cnt;
if( curIdx > idx ) return iter->val;
}
assert( false );
return -1;
}
inline int getMaxDiff( int idx, Row *last, Row *current, Row *next, const int & width ){
assert( idx >= 0 );
vector<int> diffs;
PixelVal curVal;
curVal = accessRow( idx, *current );
if( idx - 1 >= 0 ){
//left
diffs.push_back( abs( accessRow( idx - 1, *current ) - curVal ) );
//upper left
if( last ) diffs.push_back( abs( accessRow( idx - 1, *last ) - curVal ) );
//lower left
if( next ) diffs.push_back( abs( accessRow( idx - 1, *next ) - curVal ) );
}
if( idx + 1 <= width - 1 ){
//right
diffs.push_back( abs( accessRow( idx + 1, *current ) - curVal ) );
//upper right
if( last ) diffs.push_back( abs( accessRow( idx + 1, *last ) - curVal ) );
//lower right
if( next ) diffs.push_back( abs( accessRow( idx + 1, *next ) - curVal ) );
}
//up
if( last ) diffs.push_back( abs( accessRow( idx, *last ) - curVal ) );
//down
if( next ) diffs.push_back( abs( accessRow( idx, *next ) - curVal ) );
return *max_element( diffs.begin(), diffs.end() );
}
void calcRow( Row *last, Row *current, Row *next, int &width, Res &res ){
assert( current && !current->empty() );
int i;
int idx;
Row::const_iterator rowIter;
Row* tmp[3] = { last, current, next };
typedef list<int> CalcPoints;
CalcPoints points;
for( i = 0; i < 3; i++ ){
if( !tmp[i] ) continue;
for( idx = 0, rowIter = tmp[i]->begin(); rowIter != tmp[i]->end(); rowIter++ ){
idx += rowIter->cnt;
points.push_back( idx - 1 );
}
}
CalcPoints calcIdx;
CalcPoints::const_iterator ptIter;
calcIdx.push_back( 0 );
for( ptIter = points.begin(); ptIter != points.end(); ptIter ++ ){
calcIdx.push_back( *ptIter );
if( *ptIter + 1 <= width - 1 ) calcIdx.push_back( *ptIter + 1 );
}
calcIdx.sort();
calcIdx.unique();
int repeat;
CalcPoints::const_iterator nextIdx;
for( ptIter = calcIdx.begin(); ptIter != calcIdx.end(); ptIter ++ ){
res.push_back( RleElement( \
getMaxDiff( *ptIter, last, current, next, \
width ),
1 ) );
nextIdx = ++ptIter;
ptIter --;
if( nextIdx!= calcIdx.end() ){
if( *( nextIdx ) - *ptIter < 2 ) continue;
repeat = *nextIdx - *ptIter - 1;
res.push_back( \
RleElement( \
getMaxDiff( *ptIter + 1, \
last, current, next, width ), \
repeat ) \
);
}
}
}
//FILE *stdin;
int main(void)
{
//stdin = fopen( "data.txt", "r" );
int width;
Row buff[3];
Row *rows[3];
Row *tmpRow;
Res result;
rows[0] = &buff[0];
rows[1] = &buff[1];
rows[2] = &buff[2];
while (1) {
fscanf(stdin, "%d", &width);
if (!width)
break;
printf( "%d\n", width );
result.clear();
rows[0]->clear();
rows[1]->clear();
rows[2]->clear();
while( getRow( *rows[2], width, result ) ){
tmpRow = rows[0];
rows[0] = rows[1];
rows[1] = rows[2];
rows[2] = tmpRow;
if( rows[0]->empty() ) continue;
if( rows[2]->empty() )
calcRow( NULL, rows[0], rows[1], width, result );
else
calcRow( rows[2], rows[0], rows[1], width, result );
}
if( !rows[0]->empty() )
calcRow( rows[0], rows[1], NULL, width, result );
else
calcRow( NULL, rows[1], NULL, width, result );
printResult( result );
printf( "0 0\n" );
}
printf( "0\n" );
//fclose( stdin );
return 0;
}
Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator