zoukankan      html  css  js  c++  java
  • hdu 6435 CSGO(最大曼哈顿距离)

    题目链接

    Problem Description
    You are playing CSGO.
    There are n Main Weapons and m Secondary Weapons in CSGO. You can only choose one Main Weapon and one Secondary Weapon. For each weapon, it has a composite score S.
    The higher the composite score of the weapon is, the better for you.
    Also each weapon has K performance evaluations x[1], x[2], …, x[K].(range, firing rate, recoil, weight…)
    So you shold consider the cooperation of your weapons, you want two weapons that have big difference in each performance, for example, AWP + CZ75 is a good choose, and so do AK47 + Desert Eagle.
    All in all, you will evaluate your weapons by this formula.(MW for Main Weapon and SW for Secondary Weapon)

    $$$$$$S_{MW}+S_{SW}+sum_{i=1}^{k}{|x_{MW}[i]-x_{SW}[i]|}$$$$$$
    Now you have to choose your best Main Weapon & Secondary Weapon and output the maximum evaluation.
    Input
    Multiple query.
    On the first line, there is a positive integer T, which describe the number of data. Next there are T groups of data.
    for each group, the first line have three positive integers n, m, K.
    then, the next n line will describe n Main Weapons, K+1 integers each line S, x[1], x[2], …, x[K]
    then, the next m line will describe m Secondary Weapons, K+1 integers each line S, x[1], x[2], …, x[K]
    There is a blank line before each groups of data.
    T<=100, n<=100000, m<=100000, K<=5, 0<=S<=1e9, |x[i]|<=1e9, sum of (n+m)<=300000
    Output
    Your output should include T lines, for each line, output the maximum evaluation for the corresponding datum.
    Sample Input
    2
    2 2 1
    0 233
    0 666
    0 123
    0 456
    2 2 1
    100 0 1000 100 1000 100
    100 0
    Sample Output
    543
    2000
    题意
    $$$n$$$种主武器,$$$m$$$种副武器,主/副武器都有一个主属性$$$S$$$和$$$k$$$个副属性$$$x[1], x[2], ..., x[k]$$$。如果用$$$MW$$$表示主武器,$$$SW$$$表示副武器,则一件主武器和一件副武器搭配的价值为$$$S_{MW}+S_{SW}+sum_{i=1}^{k}{|x_{MW}[i]-x_{SW}[i]|} $$$,求这样的搭配的最大值为多少。
    分析
    这道题是poj_2926_ Requirements的升级版,要做这道题,需要先知道怎样去求$$$n$$$个5维向量,两两曼哈顿距离的最大值,也就是要求$$$max{|x_i-x_j|+|y_i+y_j|+|z_i-z_j|+|p_i-p_j|+|q_i-q_j| }$$$。
    上面的代数式,看似最合理也最基本的做法,就是遍历$$$i,j$$$,计算所有向量之间的曼哈顿距离,复杂度为$$$O(C_n^2 imes m)$$$,当$$$n$$$的值很大时,暴力将会超时,所以要从很小的m入手,采用一种直觉上很反智(仅个人观点),但是对计算机很高效的算法。
    把绝对值打开会得到两种情况,比如$$$|x_i-x_j|$$$要么是$$$(x_i-x_j)$$$,要么是$$$(-x_i+x_j)$$$,$$$x_i$$$前面的系数是1/-1对应它较大/较小的情况;如果放在五维上分析的话,把两个五维向量$$$A: (a_1,a_2,a_3,a_4,a_5), B: (b_1,b_2,b_3,b_4,b_5)$$$的曼哈顿距离的代数式打开,将有$$$2^5=32$$$种情况,每种情况中,$$$a_i$$$的系数可以是$$$1$$$或$$$-1$$$,分别对应$$$a_i$$$在此情况下是较大还是较小,$$$b_i$$$也是同理,而且$$$b_i$$$的系数一定和$$$a_i$$$的系数相反。如果把$$$A$$$和$$$B$$$的系数单独提取出来,变成下面这样
    $$$$$$ egin{align} & sum_{i=1}^{5}{(t_{a_i}a_i-t_{a_i}b_i)}\ =& (a_1,a_2,a_3,a_4,a_5) imes egin{pmatrix} t_{a_1}\ t_{a_2}\ t_{a_3}\ t_{a_4}\ t_{a_5} end{pmatrix} +(b_1,b_2,b_3,b_4,b_5) imes egin{pmatrix} -t_{a_1}\ -t_{a_2}\ -t_{a_3}\ -t_{a_4}\ -t_{a_5} end{pmatrix}\[3ex] =& (a_1,a_2,a_3,a_4,a_5) imes egin{pmatrix} t_{a_1}\ t_{a_2}\ t_{a_3}\ t_{a_4}\ t_{a_5} end{pmatrix} -(b_1,b_2,b_3,b_4,b_5) imes egin{pmatrix} t_{a_1}\ t_{a_2}\ t_{a_3}\ t_{a_4}\ t_{a_5} end{pmatrix} end{align} $$$$$$ 换一个角度看问题,序列$$$ egin{pmatrix} t_{a_1}\ t_{a_2}\ t_{a_3}\ t_{a_4}\ t_{a_5} end{pmatrix}$$$,其实相当于是去衡量$$$A$$$和$$$B$$$大小的一个标准,$$$A$$$和$$$B$$$经过序列的处理,直接就可以比较大小了,并求出差值。那么用它也同样可以用来衡量所有的向量。有了衡量标准的好处是,我们就不用再把向量两两比较才能知道最大的差了,只需要用这个标准来计算出所有向量的值(也就是把每个向量乘上这个序列),用最大值减去最小值就得到了最大的差。
    虽然我们并不知道,选用哪个$$$ egin{pmatrix} t_1\ t_2\ t_3\ t_4\ t_5 end{pmatrix}$$$才是真正的最大差,才是原代数式的值,但是所有的序列包含了所有可能的情况,一定有一个序列对应着原代数式的值,只要遍历了所有的序列,最大的那个就是答案。再看一下复杂度,对于5维的向量,有$$$2^5$$$种情况,要求所有向量在这种情况下的值,所以复杂度就是$$$O(2^5 imes n)$$$,推广到k维的情况下,复杂度就是$$$O(2^kn)$$$,而先前暴力的做法复杂度则为$$$O(frac{kn(n-1)}{2})=O(kn^2)$$$。优化到这个程度,就能在限定时间求出答案了
    说完了最大曼哈顿距离怎么计算,再来看hdu的这道题是不是就容易多了,还是同样的把绝对值打开来计算,只是在每种情况下,向量的大小不光是后面k个数计算的结果,还要再加上一个常数,其他的过程都是类似的。
    总结
    做法很简单,但真的很神奇,想了很久才理解了是怎么回事,终于又学会了一道题。
    代码
    #include<stdio.h>
    typedef long long LL;
    int first[100005][5], second[100005][5];//武器的副属性
    int wf[100005],ws[100005];//武器的主属性
    LL sf[100005],ss[100005];//求和需要用long long 保存
    
    int n,m,k;
    
    int main(){
        int kase;
        LL mf,ms,ans;
        int t;
        for(scanf("%d",&kase);kase;kase--){
            scanf("%d %d %d",&n,&m,&k);
            for(int i=0;i<n;++i)
                for(scanf("%d",wf+i),t=0;t<k;++t)
                    scanf("%d",first[i]+t);
            for(int i=0;i<m;++i)
                for(scanf("%d",ws+i),t=0;t<k;++t)
                    scanf("%d",second[i]+t);
            ans=0;
            for(int i=(1<<k)-1;i>=0;--i){//用二进制代表系数的序列,并遍历11111~00000
                for(t=0;t<n;++t)sf[t]=0;
                for(t=0;t<m;++t)ss[t]=0;
                for(int w=1,j=0;j<k;j++,w<<=1){//计算在当前序列下的值
                    for(t=0;t<n;++t)
                        sf[t]=sf[t]+first[t][j]*(i&w?1.0:-1.0);
                    for(t=0;t<m;++t)
                        ss[t]=ss[t]+second[t][j]*(i&w?1.0:-1.0);
                }
                //还要加上一个常数才是最终大小
                mf=sf[0]+wf[0];
                for(t=1;t<n;++t)
                    if(mf<sf[t]+wf[t])mf=sf[t]+wf[t];
                ms=ss[0]-ws[0];
                for(t=1;t<m;++t)
                    if(ms>ss[t]-ws[t])ms=ss[t]-ws[t];
                if(ans<mf-ms)ans=mf-ms;
            }
            printf("%lld
    ",ans );
    
        }
    }
  • 相关阅读:
    Java8新特性
    为什么要使用ORM技术?和 JDBC 有何不一样?
    HTTP Status 500
    重装Oracle时出现SID已存在问题的解决办法
    数据库模式显示的Swing表格
    自然连接和等值连接
    雷林鹏分享:Java 循环结构
    雷林鹏分享:Java 运算符
    雷林鹏分享:Java 修饰符
    雷林鹏分享:Java 变量类型
  • 原文地址:https://www.cnblogs.com/tobyw/p/9524313.html
Copyright © 2011-2022 走看看