Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 314 Accepted Submission(s): 155
题意:给定一些操作(0代表添加一个点,1代表删除一个点),求这些点的最远曼哈顿距离。
可先参考POJ 2926 Requirements:http://poj.org/problem?id=2926
POJ该题思路:
以二维平面为例:
设距离最远的两点为 i, j,可知所求的最大距离必定有以下四种形式之一:
(xi-xj)+(yi-yj), (xj-xi)+(yi-yj), (xi-xj)+(yj-yi), (xj-xi)+(yj-yi) 变形一下,把相同点的坐标放到一起,
即 (xi+yi)-(xj+yj), (-xi+yi)-(-xj+yj), (xi-yi)-(xj-yj), (-xi-yi)-(-xj-yj),可以发现即去绝对值之后把同一点的坐标放在一起,对应坐标符号相同。
假如我们用0表示符号,用1表示正号,那么 (xi+yi) 可以表示为 11。
那么要表示一个维数为 dem 的所有状态,只需要用 0 ~ (2^dem-1) 的所有二进制就可以了。
于是只要对所有的点 (xi,yi),依次计算出 (xi+yi), (xi-yi), (-xi+yi), (-xi-yi)这四种形式,然后把每个点i算出来的这四种情况的最大值、最小值分别记录(更新)到数组 max[] 和 min[] 中,然后枚举每一种去绝对值的组合,组合后的最大值即为 answer。
代码:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=100010; const double INF=1e20; int n; double num[N][5],minx[1<<5],maxx[1<<5]; int main(){ //freopen("input.txt","r",stdin); while(~scanf("%d",&n)){ for(int i=0;i<n;i++) for(int j=0;j<5;j++) scanf("%lf",&num[i][j]); for(int i=0;i<(1<<5);i++){ //共有(1<<5)种状态,存储每种状态下的最大最小值 minx[i]=INF; maxx[i]=-INF; } double sum; int tmp; for(int i=0;i<n;i++) for(int j=0;j<(1<<5);j++){ //枚举每种状态 tmp=j; sum=0; for(int k=0;k<5;k++){ if(tmp&1) sum+=num[i][k]; else sum-=num[i][k]; tmp>>=1; } if(maxx[j]<sum) maxx[j]=sum; if(minx[j]>sum) minx[j]=sum; } double ans=-INF; for(int i=0;i<(1<<5);i++) if(maxx[i]-minx[i]>ans) ans=maxx[i]-minx[i]; printf("%.2f\n",ans); } return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<set> using namespace std; const int N=60010; const double INF=1e20; int n,m,num[N][10]; //map<int,int,greater<int> > mp[1<<5]; multiset<int> mst[1<<5]; multiset<int>::iterator it1,it2; int main(){ //freopen("input.txt","r",stdin); while(~scanf("%d%d",&n,&m)){ for(int i=0;i<(1<<5);i++) mst[i].clear(); int od,x; for(int i=1;i<=n;i++){ scanf("%d",&od); if(od==0){ for(int j=0;j<m;j++) scanf("%d",&num[i][j]); for(int j=0;j<(1<<m);j++){ int sum=0; for(int k=0;k<m;k++){ if(j&(1<<k)) sum+=num[i][k]; else sum-=num[i][k]; } mst[j].insert(sum); } }else{ scanf("%d",&x); for(int j=0;j<(1<<m);j++){ int sum=0; for(int k=0;k<m;k++){ if(j&(1<<k)) sum+=num[x][k]; else sum-=num[x][k]; } it1=mst[j].find(sum); mst[j].erase(it1); } } int ans=0; //map<int,int>::iterator it1,it2; for(int j=0;j<(1<<m);j++){ it1=mst[j].end(); it1--; it2=mst[j].begin(); ans=max(ans,(*it1)-(*it2)); } printf("%d\n",ans); } } return 0; }