Description
给出一张数字图,对于每个像素点求出这个点与其周围所有点差的绝对值的最大值
Input
多组输入,每组数据第一行为一个整数n(n<=1000),表示图的宽度,接下来每行两个整数a,b(a<=255,b<=10^9),分别表示此段数字大小和长度,每组数据以0 0结束,n=0时结束输入
Output
对于每组输入,在求出每个像素点与其周围点差的绝对值后按输入格式输出,即第一行为n,中间为每个数字连续段的数值和长度,以0 0结束每组输出,以0结束全部输出
Sample Input
7
15 4
100 15
25 2
175 2
25 5
175 2
25 5
0 0
10
35 500000000
200 500000000
0 0
3
255 1
10 1
255 2
10 1
255 2
10 1
255 1
0 0
0
Sample Output
7
85 5
0 2
85 5
75 10
150 2
75 3
0 2
150 2
0 4
0 0
10
0 499999990
165 20
0 499999990
0 0
3
245 9
0 0
0
Solution
首先暴力必挂QAQ
然后从答案可以看出肯定会有一些连续段答案相同,所以思路就是,先找出在原图的某一连续段中,答案值可能改变的几个像素(做标记),再一次次跳跃到这几个像素中计算它们的答案值,但是问题是,怎么样的像素才是需要计算的像素。
如上图一个map,紫色标注的都是要标记的格子,红色边框的代表这一个连续段的起始格。我们可以发现,每个连续段的起始格,都是要标记的格子,同时,每个要标记的格子,都是一个连续段起始格的周围8个格子中的一个。所以,只需要一个个枚举每个连续段的起始格,并计算它和它四周8个格子的答案值,最后统计答案的时候按照位置先后排序,答案中相同的连续段就合并。因为最多只有1000个连续段,所以不管是时间还是空间都不会超。
Code
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define size 1005
struct pix
{
int pos;//pos表示这个像素点的位置
int code;//code表示这个像素点的答案值
}outmap[size*8];
int inmap[size][2];//inmap[][0]表示这个连续段的数值,inmap[][1]表示这个连续段的长度
int width,cntp,tot;//width为图宽度,cntp为图中连续段段数,tot为图中像素点总个数
int cmp(pix x,pix y)//排序函数,对pos升序排
{
return x.pos<y.pos;
}
int getnum(int pos)//返回原图上pos位置上的数值
{
int p=0,i=0;
while(p<pos)
p+=inmap[i++][1];
return inmap[i-1][0];
}
int getcode(int pos)//计算pos位置上的答案
{
int num=getnum(pos),ret=0;
int row=(pos-1)/width;//pos所处排数
int col=(pos-1)%width;//pos所处列数
for(int i=row-1;i<=row+1;i++)//枚举pos周围八个方向
for(int j=col-1;j<=col+1;j++)
{
int tpos=i*width+j;
if(i<0||j>=width||j<0||tpos==pos-1||tpos>=tot)
continue;
int temp=getnum(tpos+1);
if(ret<abs(temp-num))
ret=abs(temp-num);
}
return ret;
}
int main()
{
while(scanf("%d",&width)&width>0)
{
int num,len;
cntp=tot=0;//初始化
while(scanf("%d%d",&num,&len)&&len>0)
{
inmap[cntp][0]=num;
inmap[cntp++][1]=len;
tot+=len;
}
printf("%d\n",width);//按格式输出
int pos=1,k=0;
for(int p=0;p<=cntp;p++)//枚举每个连续段
{
int row=(pos-1)/width;//每个连续段起始点所处行数
int col=(pos-1)%width;//每个连续段起始点所处列数
for(int i=row-1;i<=row+1;i++)//枚举起始点周围八个点
for(int j=col-1;j<=col+1;j++)
{
int tpos=i*width+j;//此处tpos其实是真实tpos标号减一
if(i<0||j<0||j>=width||tpos>=tot)//超出图范围舍去
continue;
outmap[k].pos=tpos+1;
outmap[k++].code=getcode(tpos+1);
}
pos+=inmap[p][1];//跳跃到下一连续段起始点
}
sort(outmap,outmap+k,cmp);//对答案按pos升序排序
pix temp=outmap[0];
for(int i=0;i<k;i++)
{
if(outmap[i].code==temp.code)//连续则不输出
continue;
printf("%d %d\n",temp.code,outmap[i].pos-temp.pos);
temp=outmap[i];
}
printf("%d %d\n",temp.code,tot-temp.pos+1);//最后一部分
printf("0 0\n");//按格式输出
}
printf("0\n");//按格式输出
return 0;
}