poj1009

算法证明:记输入图像中{像素起点,起点的相邻点,左下角点}为集合A,输出图像中像素起点为集合B,那么B是A的子集。
证明:
假设存在点x属于集合B,但是不属于集合A,即输出中的起始点不属于输入中的{起始点、与起始点相邻的点、左下角点}
对于输入图像:
1)若x是左上角点
因为是第一个点,无论输入图还是输出图,都是线段的起始点。
即该点属于A,也属于B。
故假设不成立。

2)若x是右上角点
. . a x
. . b c
. . . .
因为a、b、c都不是起始点,
故上图可以转化为:
. a a x
. b b b
. . . .
此时x本身为起点,当然既属于A,又属于B。
故假设不成立。

3)若x是左下角点
假设直接不成立!
因为此点作为特殊点已加入A,故该点不管是否在B中出现,一定在A中。但,为什么要把它作为特殊点呢?
. .
a b .
x c .
此时左下角的点虽然不是起始点,也不与任一个起始点相邻,但是此处的输出值为|a-x|,
但是倒数第二行最右侧的x,输出值为max{|x-e|、|x-d|、|x-f|、|x-g|、|x-h|},
故,该点必须要考虑。
. .       d e
a a .     f x
x x .     g h

4)若x是右下角点
. a a a
. d d x
此处x本身为起始点也!,属于A,同2)所述。
故,假设不成立。

5)若x是非边界点
. . . . .
. a b c .
. d x e .
. f g h .
. . . . .
因为a、b、c、d、e、f、g、h都不是起始点
那么,a=b=c d=x=e f=g=h
故上图可入下转化:
. . . . .
a a a a .
x x x x .
f f f f .
. . . . .
注意:最左侧一列可能是边界,也可能不是。
此时,第三列的x与第二列的x在输出中对应的值相同,因此不可能是输出线段的起点。
此时x虽然不属于A,但同时不可能属于B。
故假设不成立。

综上所述,不存在一个点x属于B但是不属于A。反之,若一个点属于B,那么一定属于A。


/*
题意:图像使用RLE编码(详细内容请自查)方式进行存储。现有边缘检测算法,输出的像素值为输入像素值与周围像素值差值的最大绝对值。
      请使用RLE编码输出经过边缘检测算法处理后的图像。 
算法:记输入图像中{像素起点,起点的相邻点,左下角点}为集合A,输出图像中像素起点为集合B,那么B是A的子集。
       因此,可将暴力枚举法(枚举输入的每个像素点)转化为枚举集合A中的点。 
      1.找出所有输入像素的起点及其周围的点+左下角点,记为集合A 
      2.枚举集合A中的每个点a,求其与周围像素点差值的最大绝对值,其结果记为集合B 
      3.将集合B的结果整理后输出 
难度:****
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>

int pairs[1010][3];  // pairs[i][0]=m:第i组输入的像素值为m  pairs[i][1]=n:第i组输入像素的个数为n  pairs[i][2]=p:第0-i组输入的共有n个像素 
int possible[10000]; // possible[i]=j:集合A中第i个元素,其位置为j 
int ans[10000];		 // ans[i]=j:集合B中的第i个元素,其值j对应输出图像的值 
int indexes[9][3] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1 }, {0, 0}, {0, 1}, {1, -1 }, {1, 0}, {1, 1}};	// 共9个方向,(0,0)为原地不动 

int comp(const void*a,const void*b)	
{
	return *(int*)a-*(int*)b;
}

// 输入像素位置key,返回其对应的像素值 
int binarySearch(int key,int pairs_num)
{
	int low = 0;
	int high = pairs_num - 1;
	int mid;
	while (low < high)
	{
		mid = (low+high) / 2;
		(pairs[mid][2] <= key)? low = mid + 1 : high = mid;
	}
	return pairs[low][0];
}

// 输入像素位置idx,返回与周围点差值的最大绝对值 
int getMaxValue(int idx,int sum_pixels,int pairs_num,int width,int height)
{
	int max = -1;
	int center = binarySearch(idx,pairs_num);
	int row = idx / width;
	int column = idx % width;
	
	// 枚举像素idx周围的九个像素点loc,计算差值 
	for (int i=0; i<9; i++)
	{
		int r = row + indexes[i][0];
		int c = column + indexes[i][1];
		if (r < 0 || r >= height || c < 0 || c >= width)
		{
			continue;
		}
		int loc = r * width + c;
		int around =  binarySearch(loc,pairs_num); // 像素loc对应的像素值 
		int diff = abs(center-around);
		if (diff >= max)
		{
			max = diff;
		}
	}
	return max;
}

int main()
{
	int width,height;		// the width and height of the image
	while (true)
	{
		scanf("%d",&width);
		
		if (width == 0)
		{
			break;
		}
		
		// init arrays
		memset(pairs,0,sizeof(pairs));
		memset(possible,0,sizeof(possible));
		memset(ans,-1,sizeof(ans));
		
		int pairs_num = 0;		// the number of the input pairs
		int pixels_num = 0;		// the number of the total pixels 
	    /*
        pairs 0   1   2
          0   15  4   4
          1   100 15  19
          2   25  2   21
          ... ... ..  ..
	    */
		while (true)
		{
			scanf("%d%d",&pairs[pairs_num][0],&pairs[pairs_num][1]);	// pairs[i][0]:pixel value   pairs[i][1]:the number of the same pixel
			if (pairs[pairs_num][0] == 0 && pairs[pairs_num][1] == 0)
			{
				break;
			}
			pixels_num += pairs[pairs_num][1];
			if (pairs_num == 0)
			{
				pairs[pairs_num][2] = pairs[pairs_num][1];	
			}
			else
			{
				pairs[pairs_num][2] = pairs[pairs_num-1][2] + pairs[pairs_num][1];	// pairs[i][2]:the sum of the pixels from pair 0 to pair i
			}
			pairs_num++;
		}
		
		// the height of the image
		height = pixels_num / width;
		
		// 根据输入图像的线段起点计算其周围9个点(包含自身)的像素位置, 
		int t = 0;
		int possible_num=0;
		for (int i=0; i<pairs_num; i++)
		{
			int possible_pixel;
			for (int j=0; j<9; j++)
			{
				// 第i个起点的坐标(row,column) 
				/*
				等价与 row =  pairs[i-1][2] / width;
				       column = pairs[i-1][2] %width;
				因为: pairs[i-1][2] +  pairs[i][1] = pairs[i][2] 
				但是如果使用 pairs[i-1][2],还需要考虑i=0的情况 
				*/
				int row = (pairs[i][2] - pairs[i][1]) / width;		// 等价于pairs[i-1][2]/width 
				int column = (pairs[i][2] - pairs[i][1]) % width;
				
				// 计算周围的9个点 
				int r = row + indexes[j][0];
				int c = column + indexes[j][1];
				
				// 超出边界 
				if (r < 0 || r >= height || c < 0 || c >= width)
				{
					continue;
				}
				// possible_pixel:输入图像中的像素点位置,该位置对应的像素可能是输出图像中某像素的起点 
				possible_pixel = r * width + c;
				// 检查该像素是否已经存储在possible数据中 
				int k=0;
				for (k=0; k<possible_num; k++)
				{
					if (possible[k] == possible_pixel)
					{
						break;
					}
				}
				// possible[i]=j:第i个输出图像中可能的起点在输入图像中的位置是j 
				if (k >= possible_num)
				{
					possible[possible_num++] = possible_pixel;
				}
			}
		}
		// 左下角的点 
		possible[possible_num++] = width*(height-1);		// 至此,集合A求毕。 

		// 对数组possible进行排序,排序后再处理可保证输出像素的有序性 
		qsort(possible,possible_num,sizeof(int),comp);
		
		// ans[i]=j:第i个像素与周围点差值的绝对值最大是j 
		for (int i=0; i<possible_num; i++)
		{
			ans[i] = getMaxValue(possible[i],pixels_num,pairs_num,width,height);
		}

		
		// 输出结果 
		possible[possible_num] = pixels_num;	// 此设置方便最后线段的输出 
		printf("%d\n",width);
		for (int i=0; i<possible_num; )
		{
			int start = i;
			while (ans[start] == ans[i])
			{
				i++;
			}
			printf("%d %d\n",ans[start],possible[i]-possible[start]);
		}
		printf("0 0\n");
	}
	// 此处输出很重要! 
	printf("0\n"); 
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kangwq2017

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值