poj1009

来源:互联网 发布:软件立项申请表 编辑:程序博客网 时间:2024/06/05 09:11
算法证明:记输入图像中{像素起点,起点的相邻点,左下角点}为集合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 imagewhile (true){scanf("%d",&width);if (width == 0){break;}// init arraysmemset(pairs,0,sizeof(pairs));memset(possible,0,sizeof(possible));memset(ans,-1,sizeof(ans));int pairs_num = 0;// the number of the input pairsint 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 pixelif (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 imageheight = 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"); }


0 0
原创粉丝点击