今天做到PKU第1009题,将题目描述读了三四遍,也没看懂到底是何意,可能是英文太差了吧,于是乎,偷取捷径,去网上了搜了一下,嘿,还真的搜了一篇关于此题的中文描述,原文链接如下:
http://www.nocow.cn/index.php/PKU/1009
其中提到游程长度编码,其意是相同的一串数字用一个pair对来表示,比如若有100个80连续,那就用100 80来表示,这个是理解题意的关键。
现在理解题意了,也要开始思索了,想用什么方法来解决它,题目说最多有最多1000个游程表示,而所有的图像包括2-1,000,000,000个像素,这数据量也太惊人了,要想个法子才行。
悲剧,我前后用了将近一个周的时间,想出了个算法,并实现了,在G++也测试通过了,用时感觉也不多,且PKU1009上的示例数据进行测试,结果也都准确无误,可一Judge, 又是TLE。心里这个难受啊。
不管结果如何,先把解题思路说下:
1)将输入的每个图像数据对用二维数组存储,列长为3,其中第i行第0列代表的是该数据对的第一个元素在图像数据中的位置,图像数据的每一个像素顺序排序,从0开始,最后一个是像素总数减1;第i行第1列代表是该数据对总共有多少个;第i行第2列代表是该数据值;譬如:对于PKU1009上输入的第一组数据,这样存储:(0,4,15),(4,15,100),(19,2,25),(21,2,175),(23,5,25),(28,2,175),(30,5,25)
2)对每一组图像数据对循环处理: 判断每个像素的位置,是左,是右,是上,是下,是左上,左下,右上,右下,分别处理,对于内部的元素,分为两种情况,一种是判断其数据量是否巨大,若巨大,那肯定中间一部分经计算后的像素值为0,这一部分就没有必须进行计算了,这样可以节约时间,中间这一部分在原图像数据中的区间位置一定要算法好,不然会有错误的。
附上源代码,若有人指出费时所在,不胜感激。
#include<iostream>
using namespace std;
#define MAX_PAIR 1000
long source_data[MAX_PAIR][3]; //此为图像对数据
long width,height; //图像的宽度及其高度
int no; //共有多少图像对
//获取位置pos在图像中的像素值
int get_value(long pos)
{
for(int i=0;i<no-1;i++)
{
if(pos>=source_data[i][0]&&pos<source_data[i+1][0])
return source_data[i][2];
}
return source_data[no-1][2];
}
//求两个数相减后的绝对值
int abs_sub(int a,int b)
{
return a-b<0?b-a:a-b;
}
//计算位置在center处的像素输出的像素值
int calc_value(int left_top,int up_top,int right_top,int left_mid,int center,int right_mid,int left_bottom,int down_bottom,int right_bottom)
{
int max=abs_sub(left_top,center);
if(abs_sub(up_top,center)>max)
max=abs_sub(up_top,center);
if(abs_sub(right_top,center)>max)
max=abs_sub(right_top,center);
if(abs_sub(left_mid,center)>max)
max=abs_sub(left_mid,center);
if(abs_sub(right_mid,center)>max)
max=abs_sub(right_mid,center);
if(abs_sub(left_bottom,center)>max)
max=abs_sub(left_bottom,center);
if(abs_sub(down_bottom,center)>max)
max=abs_sub(down_bottom,center);
if(abs_sub(right_bottom,center)>max)
max=abs_sub(right_bottom,center);
return max;
}
//如果在图像第一行
int res_top(long pos)
{
int temp=get_value(pos);
return calc_value(temp,temp,temp,get_value(pos-1),temp,get_value(pos+1),get_value(pos+width-1),get_value(pos+width),get_value(pos+width+1));
}
//如果在图像左边列
int res_left(long pos)
{
int temp=get_value(pos);
return calc_value(temp,get_value(pos-width),get_value(pos-width+1),temp,temp,get_value(pos+1),temp,get_value(pos+width),get_value(pos+width+1));
}
//如果在图像右边列
int res_right(long pos)
{
int temp=get_value(pos);
return calc_value(get_value(pos-width-1),get_value(pos-width),temp,get_value(pos-1),temp,temp,get_value(pos+width-1),get_value(pos+width),temp);
}
//如果在图像最后一行
int res_bottom(long pos)
{
int temp=get_value(pos);
return calc_value(get_value(pos-width-1),get_value(pos-width),get_value(pos-width+1),get_value(pos-1),temp,get_value(pos+1),temp,temp,temp);
}
//左上角
int res_top_left(long pos)
{
int temp=get_value(pos);
return calc_value(temp,temp,temp,temp,get_value(pos),get_value(pos+1),temp,get_value(pos+width),get_value(pos+width+1));
}
//右上角
int res_top_right(long pos)
{
int temp=get_value(pos);
return calc_value(temp,temp,temp,get_value(pos-1),get_value(pos),temp,get_value(pos+width-1),get_value(pos+width),temp);
}
//左下角
int res_bottom_left(long pos)
{
int temp=get_value(pos);
return calc_value(temp,get_value(pos-width),get_value(pos-width+1),temp,temp,get_value(pos+1),temp,temp,temp);
}
//右下角
int res_bottom_right(long pos)
{
int temp=get_value(pos);
return calc_value(get_value(pos-width-1),get_value(pos-width),temp,get_value(pos-1),temp,temp,temp,temp,temp);
}
//内部,非边界
int res_normal(long pos)
{
return calc_value(get_value(pos-width-1),get_value(pos-width),get_value(pos-width+1),get_value(pos-1),get_value(pos),get_value(pos+1),get_value(pos+width-1),get_value(pos+width),get_value(pos+width+1));
}
//获取像素pos在图像中的列号, 以0始
long get_col(long pos)
{
return pos%width;
}
//获取像素pos在图像中的行号, 以0始
long get_lin(long pos)
{
return (pos-get_col(pos))/width;
}
//主函数
int main()
{
int value,i,res_value=0; //value:输入图像数据对的数据值,res_value: 输出图像数据对的数据值
long pos=0,size,res_size=0; //pos:当前的像素的序号,size:输入图像数据对的长度,res_size:输出图像数据对的长度
no=0;
while(cin>>width)
{
if(width==0)
{
cout<<0<<endl;
return 0;
}
while(cin>>value>>size)
{
if(value==0&&size==0)
{
//图像数据输入完成,开始处理输入图像数据
cout<<width<<endl;
height=pos/width;
res_value=res_top_left(0);
res_size=0;
for(i=0;i<no;i++)
for(pos=source_data[i][0];pos<source_data[i][0]+source_data[i][1];pos++)
{
long col=get_col(pos);
long lin=get_lin(pos);
int temp;
//判断当前像素的位置,上?下?左?右?左上?左下?右上?右下?内部?
if(lin==0&&col==0)
{
temp=res_top_left(pos);
}
else if(lin==0&&col==width-1)
{
temp=res_top_right(pos);
}
else if(lin==height-1&&col==0)
{
temp=res_bottom_left(pos);
}
else if(lin==height-1&&col==width-1)
{
temp=res_bottom_right(pos);
}
else if(lin==0)
temp=res_top(pos);
else if(lin==height-1)
temp=res_bottom(pos);
else if(col==0)
temp=res_left(pos);
else if(col==width-1)
temp=res_right(pos);
else
{
//在内部,将大数据对的中间置0,跳过为0的区间,往下面计算
if(source_data[i][0]+width+1==pos&&source_data[i][0]+source_data[i][1]-width-1>source_data[i][0]+width+1)
{
temp=0;
if(temp==res_value)
{
res_size+=source_data[i][1]-2*width-2;
}
else
{
cout<<res_value<<" "<<res_size<<endl;
res_value=0;
res_size=source_data[i][1]-2*width-2;
}
pos=source_data[i][0]+source_data[i][1]-width-2;
continue;
}
else
temp=res_normal(pos);
}
if(temp==res_value)
res_size++;
else
{
cout<<res_value<<" "<<res_size<<endl;
res_value=temp;
res_size=1;
}
}
cout<<res_value<<" "<<res_size<<endl;
cout<<0<<" "<<0<<endl;
no=0;
pos=0;
break;
}
//构建输入数据对数据
source_data[no][0]=pos;
source_data[no][1]=size;
source_data[no][2]=value;
pos+=size;
no++;
}
}
}