您的位置:首页 > 其它

hdu 4666 (经典求曼哈顿距离 + multiset容器)

2013-08-14 10:57 302 查看
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 题意:给定一些操作(0代表添加一个点,1代表删除一个点),求这些点的最远曼哈顿距离 以二维平面为例:
设距离最远的两点为 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。
 要用到多集合容器(multiset);      一个集合(set)是一个容器,它其中所包含的元素的值是唯一的。集和多集的区别是:set支持唯一键值,set中的值都是特定的,而且只出现一次;而multiset中可以出现副本键,同一值可以出现多次。例如: mst[j].insert(sum); 插入一个元素;   则这个元素在容器可能有多个,不是唯一的。所以像set那样,一个值对应一个健值是不行星的,所以往往要多个健值来映射元素, 所以有 j和一个指向该元素的迭代器,这两个健值来映射这个元素sum.   另外几个函数功能。 begin() 返回指向第一个元素的迭代器end() 返回指向最后一个元素之后的迭代器,不是最后一个元素  (要减1,才是指到最后一个元素)clear() 清除所有元素erase() 删除集合中的元素find() 返回一个指向被查找到元素的迭代器insert() 在集合中插入元素 #include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
using namespace std;
const int N=60010;
const double INF=1e20;
int n,m,num
[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++){    //算出要删除的点的sum值。
                    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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: