这是一道有挺难的题目。英语硬伤。好吧,我承认我在百度上找了翻译。
题目大体意思我就不说了,百度有翻译。。
这道题目一开始我是没有任何头绪的,因为,直接对像素点暴力的话肯定TLE。。开二维数组然后MLE的弱智想法我肯定不会去想。。所以,主要是对时间复杂度的优化。
感谢 这个博客的代码给了我很大的启发。
解题思路如下:
根据题目给出的条件——pair最多只有1000对,然后仔细思考会发现,如果只对像素发生变化的地方进行计算——也就是题目里说的编码了。
这个的证明我找了好久没找到,一些博客里给出的证明链接已经失效了。
但是这样是可行的,我也不知道为什么可行,找不到证明。。不过即使是知道了算法,我还是在写代码的过程中出现了问题。某个地方少写了一个等于号,然后WA了两次。其实这样的——我们需要对最后一个点进行编码。。因为,。。因为我也不知道为什么(不过这里似乎给粗了解释)。
然后我把某组数据用excel画粗来了。。嗯,excel对这道题目来说是一个很好的辅助工具。
看一组数据吧
30
0 10
10 62
5 20
15 62
5 20
25 6
5 15
0 9
25 6
0 0
用excel画出来是这样的
其中需要编码的点我用金黄色的标记了粗来,确定编码位置的点橘黄色的标记了,编码完之后是这样的
这里要尤其注意,最后的最后,一定要在最后进行一次编码,也就是其实已经超出长度的那个地方。。但是就是一定要在那个excel表第8行和第15行的那里编码一次。。不然就会有bug。体现到代码里面就是 进行跳跃的标记变量p要做到等于pairnum的地方。。实际上有数字的地方只是0~pairnum-1。。for(p = 0; p <= pairnum; ++p)。。我就是少写了那个等号。。然后WA两次。
下面是我的代码:
#include <cstdio>
#include <algorithm>
#define MAX_PAIR 1111
#define abs(a) ((a)>0?(a):(-a))
#define max(a,b) ((a)>(b)?(a):(b))
typedef struct outmappix{
int pos, code;
} pix;
int width, totlen;
int pixmap[MAX_PAIR][2];
pix outmap[MAX_PAIR*8];
int getval(int pos);
int getcod(int pos);
void swap(pix* a, pix* b);
int cmp(const void* a, const void * b);
int main(int argc, char const *argv[])
{
while(scanf("%d", &width) != EOF && width != 0){
int pixval, pixlen;
int inpairnum = totlen = 0;
while(scanf("%d%d", &pixval, &pixlen) && (pixlen || pixval)) {
pixmap[inpairnum][0] = pixval;
pixmap[inpairnum][1] = pixlen;
totlen += pixlen;
inpairnum ++;
}
int outpairnum = 0, curpos = 0;
for (int p = 0; p <= inpairnum; ++p){
int row = curpos/width;
int col = curpos%width;
for (int i = row-1; i <= row+1; ++i){
for (int j = col-1; j <= col+1; ++j){
int tmppos = i*width+j;
if(i<0 || j<0 || j>=width || tmppos >= totlen){
continue;
}
outmap[outpairnum].pos = tmppos;
outmap[outpairnum].code = getcod(tmppos);
outpairnum ++;
}
}
curpos += pixmap[p][1];
}
qsort(outmap, outpairnum, sizeof(pix), cmp);
printf("%d\n", width);
pix tmp = outmap[0];
for (int i = 0; i < outpairnum; ++i){
if(tmp.code == outmap[i].code){
continue;
}
printf("%d %d\n", tmp.code, outmap[i].pos-tmp.pos);
tmp = outmap[i];
}
printf("%d %d\n", tmp.code, totlen-tmp.pos);
printf("0 0\n");
}
printf("0");
return 0;
}
int getval(int pos)
{
int p = 0;
for(int i = 0; i <= pos; i += pixmap[p++][1]);
return pixmap[p-1][0];
}
int getcod(int curpos)
{
int ans = 0;
int val = getval(curpos);
int row = curpos / width;
int col = curpos % width;
for (int i = row-1; i <= row+1; ++i){
for(int j = col-1; j <= col+1; ++j){
int tmppos = i*width+j;
if(i<0 || j<0 || j>=width || tmppos >= totlen){
continue;
}
int tmpval = getval(tmppos)-val;
tmpval = abs(tmpval);
ans = max(ans, tmpval);
}
}
return ans;
}
int cmp(const void* a, const void* b)
{
pix* x = (pix*)a;
pix* y = (pix*)b;
return x->pos - y->pos;
}
然后不得不提出来的是,从这个题目里面学会了用STL里面的qsort函数。。。竟然用了函数指针回调函数。so。又是一次不错的学习。再次感谢这个博客!