北大ACM(1009Edge Detection)代码

/*
	Memory 172K Time 16MS
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/*
	对于图像进行边缘检测编码。简单边缘检测算法规则如下
		输出像素值设置为它与输入图像中所有周围像素之间的差的最大绝对值。 如下:
		15  15  15  15  100 100 100
		100 100 100 100 100 100 100
		100 100 100 100 100 25  25
		175 175 25  25  25  25  25
		175 175 25  25  25  25  25

		输出如下
		85  85  85  85  85  0  0 
		85  85  85  85  85  75 75 
		75  75  75  75  75  75 75
		75  150 150 75  75  75 0
		0   150 150 0   0   0  0  
*/
/*		先需要编写一个程序 利用行程编码(RLE) 对所有图像进行编码 
		程序输入格式如下
*/
	///	 w		表示像素值的宽度 也就是每一列的长度
	///	 a b	表示RLE 对  存在像素值 a的b个对象
	///  0 0	表示输入结束
	///	 0		表示没有数据需要处理 循环结束		


#define SIZE 1010			//表示输入图像数据的对数大小


struct Pixel
{
	int value;			//表示数据值
	int pos;			//数据值所在图像的位置
}outData[SIZE * 9];

int width;				//图像宽度
int inNum, outNum;		//输入数据的数量和输出数据的数量
int total;				//数据的总长度

int inData[SIZE][2];	//下标[i][0]表示数据值 下标[i][1]表示的是数值所在的位置

int cmp(const void* lhs, const void * rhs);			//比较两个Pixel结构的下标然后进行排序
int getVal(int pos);								//获取该位置上的数据
int cal(int pos);									//获取该位置的值与周围数值的最大差值
void solve();										//调用其他函数来进行排序并打印


int main()
{
	int i, j;
	
	while (scanf_s("%d", &width) && width)			//持续录入数据
	{
		total = 0;
		i = 0;
		printf_s("%d\n", width);
		while (scanf_s("%d %d", &inData[i][0], &inData[i][1]))	//录入单对数据
		{
			j = inData[i][1];				//记录该数据长度
			inData[i][1] = total;			//将数据长度改为数据开始位置
			total += j;						//数据总长度每次加上单对数据长度
			if (j == 0) break;				//数据长度为0 结束录入
			++i;
		}
		///记录输入数量
		inNum = i;
		///录入数据进行处理
		solve();
	}

	printf_s("0\n");
	return 0;
}

int cmp(const void * lhs, const void * rhs)
{
	return ((struct Pixel*)lhs)->pos -  ((struct Pixel*)rhs)->pos;
}

int getVal(int pos)
{
	int low = 0, high = inNum - 1;			
	int mid;

	///使用二分查找法来进行查找传递的pos位于图像数据中的哪一个位置上
	while (low <= high)
	{
		mid = (low + high) / 2;

		if (inData[mid][1] > pos)		//当前位置大于查找位置时,表示需要向前查找
			high = mid - 1;
		else
			low = mid + 1;			//否则表示需要向后查找
	}
	return inData[high][0];
}

int cal(int pos)			//返回该位置的数据与周围数据的最大差值
{
	int ret = 0;	//返回值
	int row, col;	//行与列
	int p;			//周围元素坐标
	int i, j;
	int value;		//单次的差值
	int tmp_value = getVal(pos);		//获取当前位置的数据,避免重复调用

	row = pos / width;
	col = pos % width;

	////对于赋值的条件来说,避免不必要的循环。当处于第一行时  无需要去比较上一行的元素 ,当处于最后一行时 无需要去比较下一行的元素
	for(i =row -1; i < row + 2; ++i)
		for (j =col -1; j < col+2; ++j)	//列也是一样的 处于第一列和最后一列时无需要去比较不存在的列
		{
			p = i * width + j;

			if (i < 0 || j < 0 || j >= width || p >= total || p == pos) 
				continue;

			value = abs(getVal(p) - tmp_value);
			if (value > ret)
				ret = value;
		}

	return ret;
}

void solve()
{
	int i, j, k;
	int pos;
	int row, col;
	struct Pixel cur;			//用于打印时计算数值的数量

	outNum = 0;

	for (i = 0; i <= inNum; ++i)
	{
		row = inData[i][1] / width;
		col = inData[i][1] % width;

		///通过循环来遍历每个数据值,并计算出该数据值与周围数据的差值,然后添加到结构中
		for(j = row - 1; j < row + 2; ++j)
			for (k = col - 1; k < col + 2; ++k)
			{
				pos = j * width + k;

				if (j < 0 || pos < 0 || pos >= total)
					continue;

				outData[outNum].value = cal(pos);
				outData[outNum].pos = pos;
				++outNum;
			}
	}
	///对结构进行排序
	qsort(outData, outNum, sizeof(struct Pixel), cmp);
	cur = outData[0];

	//进行打印
	for (i = 0; i < outNum; ++i)
	{
		if (cur.value == outData[i].value)			//如果数据值相同的话,不进行显示,直接循环下一个。
			continue;
		printf_s("%d %d\n", cur.value, outData[i].pos - cur.pos);	//直到存在不同的数据值的时候进行显示,显示该数据值和数据值的数量
		cur = outData[i];
	}
	printf("%d %d\n", cur.value, total - cur.pos);		//最后还需要打印出最后一个的值
	printf_s("0 0\n");
}

猜你喜欢

转载自blog.csdn.net/David_TD/article/details/83655836