您的位置:首页 > 其它

pku acm 1009

2011-08-23 13:16 337 查看
-)常规解法,Time Limit Exceeded
设一个点x与周围8个点相减后绝对值的最大值为edv值。
思想:
1)同一行中的相邻点x1,x2,如果x1已经求得它周围的8个点那么对于x2而言只需要计算另外3个点就可以了。
边界情况就是:对于左边界的点必须求周围8个点
2)当两个相邻点x1,x2的edv值都是0时,检查是否存在接下来很多点值都相等的情况,这那么可以加速。



尽管使用了以上两种技术但是速度仍然不够快,平台通不过。
#include <iostream>
#include <cstdio>
#include <string>
#include <cmath>
using namespace std;

#define L_N(x) (x - 1)
#define R_N(x) (x + 1)
#define U_N(x,width) (x - width)
#define D_N(x,width) (x + width)

#define LU_N(x,width) L_N(U_N(x,width))
#define RU_N(x,width) R_N(U_N(x,width))
#define LD_N(x,width) L_N(D_N(x,width))
#define RD_N(x,width) R_N(D_N(x,width))

#define L_BORDER(x,width) (((x-1)%width==0)?1:0)
#define R_BORDER(x,width) (((x)%width==0)?1:0)
#define U_BORDER(x,width) (((x) >= 1 && (x) <= width)?1:0)
#define D_BORDER(x,total,width) (((x) > (total - width) && (x) <= (total))?1:0)

int arr[1000][2];
int width;
int aa[9];
int totalPixs;
int count;

int getPix(int x)//x >= 1
{
int i;
for(i = 0; i < count; i++)
{
if(x <= arr[i][1])
return arr[i][0];
}
return -1;
}

int getIndex(int x)//x >= 1
{
int i;
for(i = 0; i < count; i++)
{
if(x <= arr[i][1])
return i;
}
return -1;
}

void get8NPix(int i)
{
int curPix,tPix;
curPix = getPix(i);
int j;
for(j = 0; j < 9; j++)
aa[j] = curPix;
aa[4] = curPix;

if(!L_BORDER(i,width))
aa[3] = getPix(L_N(i));
if(!R_BORDER(i,width))
aa[5] = getPix(R_N(i));
if(!U_BORDER(i,width))
aa[1] = getPix(U_N(i,width));
if(!D_BORDER(i,totalPixs,width))
aa[7] = getPix(D_N(i,width));
if(!(L_BORDER(i,width) || U_BORDER(i,width)))
aa[0] = getPix(LU_N(i,width));
if(!(R_BORDER(i,width) || U_BORDER(i,width)))
aa[2] = getPix(RU_N(i,width));
if(!(L_BORDER(i,width) || D_BORDER(i,totalPixs,width)))
aa[6] = getPix(LD_N(i,width));
if(!(R_BORDER(i,width) || D_BORDER(i,totalPixs,width)))
aa[8] = getPix(RD_N(i,width));
}

void get3NPix(int i)
{
aa[0] = aa[1];
aa[1] = aa[2];
aa[3] = aa[4];
aa[4] = aa[5];
aa[6] = aa[7];
aa[7] = aa[8];

aa[2] = aa[5] = aa[8] = -1;
if(!(R_BORDER(i,width) || U_BORDER(i,width)))
aa[2] = getPix(RU_N(i,width));
if(!R_BORDER(i,width))
aa[5] = getPix(R_N(i));
if(!(R_BORDER(i,width) || D_BORDER(i,totalPixs,width)))
aa[8] = getPix(RD_N(i,width));
}

int getMaxDiff(int *aa)
{
int max = 0;
int i,diff;
for(i = 0; i < 4; i++)
{
if(aa[i] == -1)continue;
diff = abs(aa[4] - aa[i]);
if(diff > max) max = diff;
}
for(i = 5; i < 9; i++)
{
if(aa[i] == -1)continue;
diff = abs(aa[4] - aa[i]);
if(diff > max) max = diff;
}
return max;
}

int main()
{

int px, rle;
int begin,end,h;
int i;
//freopen("in.txt","r",stdin);

cin>>width;
while(width)
{
cout<<width<<endl;
totalPixs = count = 0;
while(cin>>px>>rle)
{
if(px == 0 && rle == 0)
break;
totalPixs += rle;//
arr[count][0] = px;
arr[count][1] = totalPixs;	//
++count;
}

int max,pmax,pcount;
get8NPix(1);
pmax = getMaxDiff(aa);
pcount = 1;
for(i = 2; i <= totalPixs; i++)
{
if(L_BORDER(i,width))
get8NPix(i);
else
get3NPix(i);
max = getMaxDiff(aa);

if(max == 0 && pmax == 0)
{
h = getIndex(i);

if(h == 0)
begin = 0;
else if(h <= count - 1)
begin = arr[h-1][1];

if(i - begin > width)
{
end = arr[h][1] - width - 1;
if(end > i)
{
pcount += end - i;
i = end;
}
}
}

if(max == pmax)
++pcount;
else
{
cout<<pmax<<" "<<pcount<<endl;
pmax = max;
pcount = 1;
}
}
cout<<pmax<<" "<<pcount<<endl;
cout<<"0 0"<<endl;

cin>>width;
}
cout<<"0"<<endl;
return 1;
}


二)下面这种方法来自一位网友,认为只有在输入值发生变化的地方才可能发生edv值的变化。(AC)



如上图中蓝色的方框正是发生输入值变化的点,那么只有这些点及其周围的8个点才可能发生edv值变化。其它点的值都不会变化。

为什么?



现假设从A到B没有发生值变化,且B周围的8个点也没有发生值变化,则很显然d1 = c1 = b1 = a1,d2 = c2 = b2 = a2, d3 = c3 = b3 = a3,因此A的edv值必与B的edv值相等。

因此如果如果从A到B发生edv值变化,那么必然是周围存在输入值变化的点。

对于这题而言,我们只需要计算输入值发生变化处的点及其周围的8个点即可。

#include <iostream>
#include <cstdio>
#include <string>
#include <cmath>
#include <map>
using namespace std;

int arr[1002][2];
int width;
int totalPixs;
int count;

bool insideImage(int dx,int dy)//dx >= 1, dy >= 1
{
if(dx >= 1 && dy >= 1 && dx <= width
&& ((dy-1)*width+dx) <= totalPixs
)
return true;
return false;
}

int getPix(int dx,int dy)//dx >= 1, dy >= 1
{
int x = (dy-1)*width+dx;
for(int i = 1; i < count; i++)
{
if(x <= arr[i][1])
return arr[i][0];
}
return -1;
}

int getEdv(int dx,int dy)
{
int cpix = getPix(dx,dy);
int max = -1,t;
for(int i = dx-1; i <= dx+1; i++)
for(int j = dy-1; j <= dy+1; j++)
{
if(insideImage(i,j))
{
t = abs(cpix-getPix(i,j));
if(t > max)max = t;
}
}
return max;
}

int main()
{
freopen("in.txt","r",stdin);

int px,rle;
map<int,int> im;
map<int,int>::iterator it;
map<int,int>::iterator tor;

cin>>width;
while(width)
{
cout<<width<<endl;

//initiation
arr[0][1] = 0;
totalPixs = 0;
count = 1;
im.clear();

while(cin>>px>>rle)
{
if(px == 0 && rle == 0)
break;
totalPixs += rle;//
arr[count][0] = px;
arr[count][1] = totalPixs;	//
//cout<<"arr["<<count<<"][0] = "<<arr[count][0]
//    <<" arr["<<count<<"][1] = "<<arr[count][1]<<endl;
++count;
}

{//begin_data_analize
for(int i = 0; i < count; i++)
{
int n = arr[i][1] + 1;//输入值发生变化的点

//求n对应的坐标表示,左上角为(1,1),x增长方向为右,y增长方向为下
int x,y,dx,dy;
if(n % width == 0)
x = width, y = n/width;
else
x = n%width, y = n/width + 1;

//求其点x,y及其周围的8个点的edv值
for(dx = x-1; dx <= x+1; dx++)
for(dy = y-1; dy <= y+1; dy++)
{
if(insideImage(dx,dy))
im.insert(make_pair(((dy-1)*width+dx), getEdv(dx,dy)));
}
}

it = im.begin();
while(it != im.end())//进行编码输出
{
tor = it;
tor++;
for(;tor != im.end() && tor->second == it->second;tor++);
if(tor == im.end())break;
cout<<it->second<<" "<<(tor->first - it->first)<<endl;
it = tor;
}
cout<<it->second<<" "<<(totalPixs - it->first + 1)<<endl;
//cout<<endl;
}//end_data_analize

cout<<"0 0"<<endl;
cin>>width;
}
cout<<"0"<<endl;
return 1;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: