zoukankan      html  css  js  c++  java
  • HDU 4666 最远曼哈顿距离

    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=4666

    关于最远曼哈顿距离的介绍:

    http://blog.csdn.net/taozifish/article/details/7574294/

    别人的解题报告链接:

    http://www.cnblogs.com/kuangbin/archive/2013/08/13/3255752.html

    我的解释:

    先看一对点,两个点的坐标分别为x(x1,x2,x3,….,xk),y(y1,y2,y3,……,yk).

    其曼哈顿距离为d = |x1-y1| + |x2-y2| +…..+|xk-yk|.

    在去绝对值后,对于点x,一共有2^k种可能的组合。

    所以,在求n个点时,用1表示正号,0表示负号,像状态压缩一样,把所有点的可能都存起来 ,求出每个点在每种状态下的值。如下面三个点的坐标为(2,3),(3,4),(4,5)。它有四种状态,四种状态下对应的值为:

    (+,+)5, 7,9

    (+,-)-1,-1,-1

    (-,+)1,1 ,1

    (-,-)-5,-7,-9

    最大值为在某种状态下的最大值减去最小值。为什么会是同种状态下呢,看上面曼哈顿距离的计算公式能发现,如果|xi-yi|为正,那么化为xi – yi,x和y对应的分量同号,如果为负,那么化为-xi – (-yi),同样是同号的。式子最终将会化成k1*x1+k2*x2 + ``` + kn*xn – (k1*x1+k2*x2+````+kn*xn)。ki为符号,可正可负。

    要想使这个式子最大,自然是某种状态下的最大值减最小值。因为|a-b|>=a-b, |a-b|>=b-a.所以虽然有些符号其实是弄错了的,但是不会影响最大值的得出。

    注意:这是我第一次使用multiset,关于删除,multiset有至少两种方法,一种是以键值删除,一种是根据迭代器位置删除···

    我一激动。用了第一种,结果一直WA···

    还有就是关于全局变量和局部变量,如果既定义了k为全局变量,又在main函数中定义了k为局部变量,那么k就是一个局部变量了,编译器对于这种错误是不会报错的····

    其实,我不是很理解这个算法,我是抄的····

    还有set<int>se.插入后是已经排好序了的,如果想调用其中的最大值,那么应该写

    multiset<int>::iterator it;
    it = se.end();
    --it;
    int t2 = (*it);

    最小值应该为int t1 = *se.begin(); 

    贴代码:

     1 #include <cstdio>
     2 #include <set>
     3 #define N 60010
     4 using namespace std;
     5 int x[N][10];
     6 int d,k;
     7 multiset<int> ms[40];
     8 void solve(int a[],int flag)
     9 {
    10     for(int i=0; i<d ; ++i)
    11     {
    12         int s=0;
    13         for(int j=0; j<k; ++j)
    14         {
    15             if(i&(1<<j))  s += a[j];
    16             else      s -=  a[j];
    17         }
    18         if(flag) ms[i].insert(s);
    19         else
    20         {
    21             multiset<int>::iterator it = ms[i].find(s);
    22             ms[i].erase(it);
    23         }
    24     }
    25 }
    26 int main()
    27 {
    28 //    freopen("in.c","r",stdin);
    29     int q;
    30     while(~scanf("%d%d",&q,&k))
    31     {
    32         d = 1<<k;
    33         for(int i=0; i<d; ++i) ms[i].clear();
    34         for(int i=1; i<=q; ++i)
    35         {
    36             int od;
    37             scanf("%d",&od);
    38             if(od == 0)
    39             {
    40                 for(int j=0; j<k; ++j)
    41                     scanf("%d",&x[i][j]);
    42                 solve(x[i],true);
    43             }
    44             else
    45             {
    46                 int p;
    47                 scanf("%d",&p);
    48                 solve(x[p],false);
    49             }
    50             int ans =0;
    51             for(int j=0; j<d; ++j)
    52             {
    53                 int t1 = *(ms[j].begin());
    54                 multiset<int>::iterator it;
    55                 it = ms[j].end();
    56                 --it;
    57                 int t2 = (*it);
    58                 if(t2-t1 > ans) ans= t2-t1;
    59             }
    60             printf("%d
    ",ans);
    61         }
    62     }
    63     return 0;
    64 }
    View Code
  • 相关阅读:
    POJ 3253 Fence Repair
    POJ 2431 Expedition
    NYOJ 269 VF
    NYOJ 456 邮票分你一半
    划分数问题 DP
    HDU 1253 胜利大逃亡
    NYOJ 294 Bot Trust
    NYOJ 36 最长公共子序列
    HDU 1555 How many days?
    01背包 (大数据)
  • 原文地址:https://www.cnblogs.com/allh123/p/3256006.html
Copyright © 2011-2022 走看看