// Input: imageNum * IMAGE{ width, PAIRS{ pixel, length} }
// 1000 0-255 1-10^9
// Output: max(pixel, pixelNear)
// Method: get enough lines to calc current line
#include <stdio.h>
#include <math.h>
#include <time.h>
typedef unsigned char BYTE;
// STRUCTS
// pairs info
struct SPAIR
{
BYTE pixel;
int length;
int index;
SPAIR *next;
};
// image info
struct SIMAGE
{
int width;
int totalLen;
SPAIR *pairs;
int curRow;
int first;
int over;
int isHead;
int isTail;
int count;
};
// output info
struct SOUTPUT
{
BYTE pixel;
int len;
};
// time info
struct STIMEINFO
{
float getPixel;
float calcOutputPixel;
float handleEasyRow;
float handleImageRow;
float handleImage;
float imageTime[1500];
};
// VARS
// current image
SIMAGE curImage;
SOUTPUT curOutput;
STIMEINFO curTime;
// read enough pixels
void readEnoughPixels(int destLen)
{
if (curImage.totalLen >= destLen || curImage.over == 1)
return;
// read enough
while (curImage.totalLen < destLen)
{
SPAIR *pair = new SPAIR;
scanf("%u %d", &pair->pixel, &pair->length);
// end flag
if (pair->pixel == 0 && pair->length == 0)
{
curImage.over = 1;
// set tail
curImage.isTail = 1;
delete pair;
return;
}
pair->index = curImage.totalLen;
// add to pairs head
pair->next = curImage.pairs;
curImage.pairs = pair;
curImage.totalLen += pair->length;
}
}
// getPixel by row, col
bool getPixel(BYTE &pixel, int row, int col)
{
clock_t start = clock();
// check row and col
if (row < 0 || col < 0 || col >= curImage.width)
return false;
int index = row * curImage.width + col;
// get enough pixels
readEnoughPixels(index + 1);
if (index > curImage.totalLen-1 && curImage.over == 1)
return false;
// look through image's pairs to get the pixel
SPAIR *pos = curImage.pairs;
while (pos && pos->index > index)
pos = pos->next;
// first time must clear the no-used pairs
if (curImage.first)
{
curImage.first = 0;
// find no-used pairs
SPAIR *found = pos->next;
SPAIR *before = pos;
while (found)
{
if (found->index + found->length + curImage.width < index)
break;
before = found;
found = found->next;
}
if (found)
{
SPAIR *temp;
while (found)
{
temp = found;
found = found->next;
delete temp;
}
before->next = 0;
}
}
clock_t end = clock();
curTime.getPixel += (float)(end - start) / CLOCKS_PER_SEC;
if (pos)
{
pixel = pos->pixel;
return true;
}
else
return false;
}
// output current pixel
void outputCurPixel()
{
printf("%d %d\n", curOutput.pixel, curOutput.len);
}
// output zero rows
void outputZeroRows(int rowNum)
{
// output the pixel
if (!curOutput.len)
{
curOutput.pixel = 0;
curOutput.len = curImage.width * rowNum;
}
else
{
if (!curOutput.pixel)
{
curOutput.len += curImage.width * rowNum;
}
else
{
// output current
outputCurPixel();
curOutput.pixel = 0;
curOutput.len = curImage.width * rowNum;
}
}
}
// get current pair by row
SPAIR* getCurPair(int row)
{
if (row < 0 || (curImage.over == 1 && curImage.totalLen-1 < row * curImage.width))
return 0;
// get enough rows
if (row * curImage.width > curImage.totalLen-1)
readEnoughPixels(row * curImage.width + 1);
// find the pair
SPAIR *pos = curImage.pairs;
while (pos && pos->index > row * curImage.width)
pos = pos->next;
return pos;
}
// calc the output pixel : get the max dist
int offset[][2] =
{
-1, -1,
0, -1,
1, -1,
-1, 0,
1, 0,
-1, 1,
0, 1,
1, 1
};
bool calcOutputPixel(int row, int col)
{
BYTE pixel, pixelNear;
clock_t start = clock();
// check if is head and tail
if (curImage.isHead && curImage.isTail)
{
SPAIR *cur = getCurPair(curImage.curRow);
if (cur && cur->length == curImage.width)
{
curOutput.pixel = 0;
curOutput.len = curImage.width;
return false;
}
}
if (!getPixel(pixel, row, col))
return false;
// calc the near pixels' dist
int dist = -1;
int temp;
for (int i = 0; i < 8; ++i)
{
// head rows jump to 3
if (curImage.isHead && i < 3)
i = 3;
// tail rows jump out
else if (curImage.isTail && i == 5)
break;
if (getPixel(pixelNear, row + offset[i][1], col + offset[i][0]))
{
temp = (int)abs((int)pixel - (int)pixelNear);
if (temp > dist)
dist = temp;
}
}
// output the pixel
if (!curOutput.len)
{
curOutput.pixel = dist;
curOutput.len = 1;
}
else
{
if (curOutput.pixel == dist)
{
++ curOutput.len;
}
else
{
// output current
outputCurPixel();
curOutput.pixel = dist;
curOutput.len = 1;
}
}
clock_t end = clock();
curTime.calcOutputPixel += (float)(end - start) / CLOCKS_PER_SEC;
return true;
}
// handle easy image rows
int handleEasyRows()
{
clock_t start = clock();
if (!curImage.isHead)
{
SPAIR *prev = getCurPair(curImage.curRow - 1);
if (prev)
{
int colStart = (curImage.curRow-1) * curImage.width - prev->index;
// cur 3 rows are the same
int rowCount = (prev->length - colStart) / curImage.width;
if (rowCount < 3)
return 0;
if (curImage.isHead)
curImage.isHead = 0;
int rowAdd = rowCount - 2;
curImage.curRow += rowAdd;
outputZeroRows(rowAdd);
return 0;
}
}
else
{
SPAIR *cur = getCurPair(curImage.curRow);
if (cur)
{
// cur 3 rows are the same
int rowCount = cur->length / curImage.width;
if (rowCount < 3)
return 0;
if (curImage.isHead)
curImage.isHead = 0;
int rowAdd = rowCount - 2;
curImage.curRow += rowAdd;
outputZeroRows(rowAdd);
return 0;
}
}
clock_t end = clock();
curTime.handleEasyRow += (float)(end - start) / CLOCKS_PER_SEC;
return 0;
}
// handle image row
int handleImageRow()
{
clock_t start = clock();
// clear easy rows
while (handleEasyRows()) ;
curImage.first = 1;
// go through the row
for (int i = 0; i < curImage.width; ++i)
{
// calc the output pixel
if (!calcOutputPixel(curImage.curRow, i))
{
if (curOutput.len > 0)
outputCurPixel();
return 0;
}
}
curImage.curRow ++;
if (curImage.isHead)
curImage.isHead = 0;
clock_t end = clock();
curTime.handleImageRow += (float)(end - start) / CLOCKS_PER_SEC;
return 1;
}
// handle image
void handleImage()
{
clock_t start = clock();
// reset last image
curImage.totalLen = 0;
curImage.curRow = 0;
curImage.first = 1;
curImage.over = 0;
curImage.isHead = 1;
curImage.isTail = 0;
curOutput.len = 0;
curImage.count ++;
SPAIR *temp;
while (curImage.pairs)
{
temp = curImage.pairs;
curImage.pairs = curImage.pairs->next;
delete temp;
}
curImage.pairs = 0;
// handle each row
while (handleImageRow()) ;
clock_t end = clock();
float runTime = (float)(end - start) / CLOCKS_PER_SEC;
curTime.imageTime[curImage.count - 1] = runTime;
curTime.handleImage += runTime;
}
#define LOCAL
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
// get image width
curImage.pairs = 0;
scanf("%d", &curImage.width);
while (curImage.width)
{
printf("%d\n", curImage.width);
handleImage();
printf("0 0\n");
scanf("%d", &curImage.width);
}
printf("0\n");
#ifdef LOCAL
printf("getPixel:%f\n", curTime.getPixel);
printf("calcOutput:%f\n", curTime.calcOutputPixel);
printf("handleEasy:%f\n", curTime.handleEasyRow);
printf("handleRow:%f\n", curTime.handleImageRow);
printf("handleImage:%f\n\n", curTime.handleImage);
for (int i = 0; i < curImage.count; i++)
{
printf("image %d: %f\n", i, curTime.imageTime[i]);
}
#endif
return 0;
}
POJ-1009-Edge Detection
最新推荐文章于 2019-05-16 17:20:50 发布