HDU 4666 Hyperspace (最远曼哈顿距离)

Hyperspace

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 314    Accepted Submission(s): 155


Problem Description
The great Mr.Smith has invented a hyperspace particle generator. The device is very powerful. The device can generate a hyperspace. In the hyperspace, particle may appear and disappear randomly. At the same time a great amount of energy was generated.
However, the device is in test phase, often in a unstable state. Mr.Smith worried that it may cause an explosion while testing it. The energy of the device is related to the maximum manhattan distance among particle.
Particles may appear and disappear any time. Mr.Smith wants to know the maxmium manhattan distance among particles when particle appears or disappears.
 

 

Input
The input contains several test cases, terminated by EOF.
In each case: In the first line, there are two integer q(number of particle appear and disappear event, ≤60000) and k(dimensions of the hyperspace that the hyperspace the device generated, ≤5). Then follows q lines. In each line, the first integer ‘od’ represents the event: od = 0 means this is an appear
event. Then follows k integer(with absolute value less then 4 × 10 7). od = 1 means this is an disappear event. Follows a integer p represents the disappeared particle appeared in the pth event.
 

 

Output
Each test case should contains q lines. Each line contains a integer represents the maximum manhattan distance among paticles.
 

 

Sample Input
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
 

 

Sample Output
0 746 0 1456 1456 1456 0 2512 5571 8922
 

 

Source
 

 

Recommend
zhuyuanchen520

 

题意:给定一些操作(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;
}
View Code

 

#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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值