poj1009 Edge Detection

题意:图片分成一格一格的像素点,输入一张图的各个像素值,输出转化后图片的像素值。首先输入图片的宽度,即一行的像素点个数。图片像素的描述方式是run length ecoding(RLE),即一组数(V,L)表示连续L个点的像素值为V。将每个像素点的值与周围的像素点值分别求差,取绝对值的最大值,这个值就是输出图片中的对应点。


分析:因为像素点个数最多有10^9个,所以不可能将所有像素点存在数组中,会MLE;也不可能每个点依次计算,会TLE。所以就找一下规律。


A A A B B

C C C C D

D D D D D


在一般情况下,连续的相同数值在转化后也是一样的,所以只要算一下每一个连续数值段的第一个点转化后的数值,而此时,这一段的第一个必会影响它周围的8个点,所以要同时更新这9个点的数值。


然后讨论特殊情况。

(1)A A A B B

    B B B B B

    C C C C C

这种情况下,第二行的B与上一行的B转化后的数值不一定是相同的。所以,当某一行存在连续数值段的第一个点时,下一行的第一个点需要特殊讨论。

(2)A A A B B

    B B B B B

    B B C C C

这种情况下,图片最左下角的那个B与上一行的B转化后的数值不同。所以,还有单独计算一下图片左下角的点。


综上,图片中需要计算的点从10^9个大大缩小,只需要计算每个连续数值段的第一个点及其周围的8个点(最多1000*9个)、连续数值段所在行的下一行的第一个点(最多1000个)、图片左下角的点(1个)。存储时也不需要存全部像素点,只需要存储输入的一组组数(最多1000组)。


唉~以为是水题,没想到花了我一下午的时间。。。还wa了好几发。。多亏了 Discuss里的测试数据呀!

附上链接吧~

Input:http://poj.org/showmessage?message_id=129813

Output:http://poj.org/showmessage?message_id=129814


#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

int width, v, l, cnt;
int in[1005][2], num[1005];

class Pix{
public:
	int val;//像素值
	int pos;//序号
	bool operator <(Pix y){
		return pos < y.pos;
	};
}out[10020];

int getcode(int pos, int l, int r){  //得到第pos个点的像素值
	if (l == r)                      //二分查找
		return in[l][0];
	int mid = (l + r) / 2;
	if (pos <= num[mid])
		return getcode(pos, l, mid);
	else if (pos>num[mid])
		return getcode(pos, mid + 1, r);
}

int getvalue(int pos){  //求第pos个点转化后的像素值
	int row = (pos - 1) / width;
	int col = (pos - 1) % width;
	int value = 0;
	int code = getcode(pos, 1, cnt - 1);
	for (int i = row - 1; i <= row + 1; i++){
		for (int j = col - 1; j <= col + 1; j++){
			int tp = i*width + j + 1;
			if (i < 0 || j < 0 || j >= width || tp > num[cnt - 1])
				continue;
			int tv = getcode(tp, 1, cnt - 1);
			if (value < abs(tv - code))
				value = abs(tv - code);
		}
	}
	return value;
}

int main(){
	while(cin >> width){
		memset(num, 0, sizeof(num));
		if (width == 0)
			break;
		cnt = 1;

		while (cin >> v >> l){     //输入
			if (v == 0 && l == 0)
				break;
			in[cnt][0] = v;
			in[cnt][1] = l;
			num[cnt] = num[cnt - 1] + l;
			cnt++;
		}

		int pos = 1, tmp=0;
		for (int k = 1; k < cnt; k++){  //按连续数值段
			int row = (pos - 1) / width;
			int col = (pos - 1) % width;

			for (int i = row - 1; i <= row + 1; i++){  //计算每一段第一个点及其周围8个点转化后的值
				for (int j = col - 1; j <= col + 1; j++){
					int tp = i*width + j + 1;
					if (i < 0 || j<0 || j >= width || tp > num[cnt - 1])
						continue;
					out[tmp].pos = tp;
					out[tmp++].val = getvalue(tp);
				}
			}

			for (int i = row; i < row + 1; i++){  //计算每一段第一个点所在行的下一行的第一个点转化后的值
				for (int j = 0; j < 1; j++){
					int tp = i * width + j + 1;
					if (i<0 || j>width || tp>num[cnt - 1])
						continue;
					out[tmp].pos = tp;
					out[tmp++].val = getvalue(tp);
				}
			}

			pos += in[k][1];
		}

		for (int i = (num[cnt - 1] - 1) / width; i < (num[cnt - 1] - 1) / width + 1; i++){
			for (int j = 0; j < 1; j++){  //计算图的左下角点转化后的值
				int tp = i*width + j + 1;
				if (i<0 || j>width || tp>num[cnt - 1])
					continue;
				out[tmp].pos = tp;
				out[tmp++].val = getvalue(tp);
			}
		}

		sort(out, out + tmp);  //按照所计算的点的序号排序

		cout << width << endl;     //开始输出
		int temp = out[0].val;
		int tpos = 1;
		for (int i = 1; i < tmp; i++){
			if (out[i].val == temp)
				continue;
			cout << temp << " " << out[i].pos - tpos << endl;
			temp = out[i].val;
			tpos = out[i].pos;
		}
		cout << temp << " " << num[cnt - 1] + 1 - tpos << endl;
		cout << "0 0" << endl;
	}
	cout << "0" << endl;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值