10 2 0 208 403 0 371 -180 1 2 0 1069 -192 0 418 -525 1 5 1 1 0 2754 635 0 -2491 961 0 2954 -2516
0 746 0 1456 1456 1456 0 2512 5571 8922
来自http://blog.csdn.net/rowanhaoa/article/details/9970399的解题报告:
题意:
给定一些操作(0代表添加一个点,1代表删除一个点),求这些点的最远曼哈顿距离。
做法:
只考虑二维空间上两个坐标之间的曼哈顿距离(x1, y1) 和 (x2, y2),|x1-x2| +|y1-y2|去掉绝对值符号后共有下列四种情况
(x1-x2) + (y1-y2), (x1-x2) + (y2-y1), (x2-x1) + (y1-y2), (x2-x1) + (y2-y1)
转化一下:
(x1+y1) - (x2+y2), (x1-y1) - (x2-y2), (-x1+y1) - (-x2+y2), (-x1-y1) - (-x2-y2)
显然,任意给两个点,我们分别计算上述四种情况,那么最大值就是曼哈顿距离。
转化后,“-”号两侧的坐标形式是一样的。维数为5,因此我们可以用二进制枚举。
最大曼哈顿距离 = max{每种情况下的最大值-最小值};
用multiset存储每种情况的值。
#include<cstdio> #include<cstring> #include<iterator> #include<set> using namespace std; struct Node{ int v; int ff; }; multiset<Node> num[1<<5]; int Hash[61100]; bool operator <(Node a,Node b) { return a.v<b.v; } int main() { int i,j,cnt,flag,tmp; int q,k; int max,ok; Node s; int nn[10]; multiset<Node>::iterator sta,tt; multiset<Node>::reverse_iterator end; while(scanf("%d%d",&q,&k)==2) { for(i=0;i<1<<k;i++) num[i].clear(); for(cnt=1;cnt<=q;cnt++) { Hash[cnt]=1; scanf("%d",&flag); if(!flag) { for(i=0;i<k;i++) scanf("%d",&nn[i]); s.ff=cnt; for(i=0;i<1<<k;i++) { tmp=i; s.v=0; for(j=0;j<k;j++) { if(tmp&1) s.v+=nn[j]; else s.v-=nn[j]; tmp>>=1; } num[i].insert(s); } } else { scanf("%d",&flag); Hash[flag]=0; } max=0; for(i=0;i<1<<k && !num[i].empty();i++) { ok=1; while(ok && !num[i].empty()) { ok=0; sta=num[i].begin(); if(Hash[sta->ff]==0) { num[i].erase(sta); ok=1; } } if(num[i].empty()) break; ok=1; while(ok) { ok=0; end=num[i].rbegin(); if(Hash[end->ff]==0) { num[i].erase(*end); ok=1; } } if(end->v-sta->v>max) max=end->v-sta->v; } printf("%d\n",max); } } return 0; }