HDU 6435 Problem J. CSGO (结论题+二进制枚举)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37025443/article/details/82011759

Problem J. CSGO

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 683    Accepted Submission(s): 353

题目链接
 

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)


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个副武器,每个武器上有k个属性

下面n行表示n个主武器,每行K+1个数字,第一个表示该武器的分数s,然后是K个属性x[1]...x[k]

下面m行同理

要你选一把主武器和一把副武器,使得他们总的分数最大,总的分数的公式就是S_{sw}+S_{mw}+\sum _{i=1}^{k} {\left |X_{mw}[i]-X_{sw}[i] \right |}

解析:

首先一开始做的时候,看到这个K<=5,我就想枚举X_{mw}[i]-X_{sw}[i]的符号,

每一位只有两种可能X_{mw}[i]-X_{sw}[i]/X_{sw}[i]-X_{mw}[i],总共有2^5种

然后我的做法是把每一个武器的状态打表记录,Mw[i][j]表示在状态i时,第j把主武器的值

(i表示的二进制,对应位为0表示改位为-,否则为+)

这里因为S无论如何都是+的,所以我们不需要管他,只要Mw[][j]都加上S_{sw}[j]

同理Sw[i][j]也打表预处理出来。

然后我就是在每一个状态i下(c=i的各位都取反),求

MAX(max(Mw[i][1..n])+max(Sw[c][1..m]),max(Mw[c][1..n])+max(Sw[i][1..m]))

最后求出来的就是答案了。

然后这样做为什么是正确的?我在写代码之前也想了很久,但是想不出来就直接莽着交了一发,发现过了。

后来队友提供了一种思路。

在我这种做法求出来的值,一定是每次的最大值,即使他对于当前是非法的情况

譬如n=2,m=2,k=2

mw1: 0 20 2          mw2:0 200000 199998

sw1:0 100000 3     sw2:0 21 300000

对于10状态时,mw的状态是10,sw的状态是01

那么mw的最大值是mw1(18) sw的最大值是sw2(299979)

但是我们发现对于10这个状态,mw1和sw2的组合是非法的。因为21>20,但是我们把这种答案作为10状态的最大值了

那么如果最后求出来最大值是非法的情况该怎么办?

那么首先我们就应该了解到上述那个公式的性质——对于非法的情况,合法的情况一定是最大的。

曼哈顿距离是两个数最大的距离。譬如mw:5 3  sw:7 1

7-5+1-3=0

7-5+3-1=4

5-7+1-3=-4

5-7+3-1=0

我们可以发现对于上面的情况|7-5|+|3-1|是最大的情况。

证明也很简单,对于5 3 7 1,如果你不按对应大小顺序进行分配符号,

那么两对里面一定有是负的,所以最大的情况一定是两对的结果都是正的情况,

那么就是他们相减后的绝对值相加。

那么明白这个性质后,其实结论就很显而易见了。

题目所求的答案就是所有曼哈顿距离里面的最大值,而曼哈顿距离又是所有情况(非法/合法)下的最大值

假定有一个非法的情况>合法的最大值,那么我们一定可以通过把非法的情况的正负号改变,

使他变成合法的情况,又合法的情况的值一定又是大于非法的情况的值,所以最后还是答案一定是一个合法的情况。

然后我那种方法一定是可以枚举出最大值的,然后最大值一定又是合法的情况(即使中间枚举不同状态时,有一些非法的最大值,但这些值最后一定是小于最后合法的最大值的),所以这种方法是可以的。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define  Min(a,b) (a<=b?a:b)
using namespace std;
typedef long long ll;
const int MAX = 1<<5;
const int MAXN = 1e5+10;
ll Mw[MAX][MAXN],Sw[MAX][MAXN];

int main()
{
    int t;
    int n,m,K;
    //read(t);
    scanf("%d",&t);
    while(t--)
    {

       scanf("%d%d%d",&n,&m,&K);
       int N = 1<<(K);
       for(int i=0;i<N;i++)
       {
           for(int j=1;j<=n;j++) Mw[i][j]=0;
           for(int j=1;j<=m;j++) Sw[i][j]=0;
       }
       for(int i=1;i<=n;i++)
       {
           int tmp;
           scanf("%d",&tmp);
           for(int j=0;j<N;j++) Mw[j][i]+=tmp;
           for(int j=1;j<=K;j++)
           {
               scanf("%d",&tmp);
               for(int w=0;w<N;w++)
               {
                   if((w&(1<<(j-1)))==0)
                   {
                       Mw[w][i]-=tmp;
                   }
                   else
                   {
                       Mw[w][i]+=tmp;
                   }
               }
           }
       }
       for(int i=0;i<N;i++)
       {
           sort(Mw[i]+1,Mw[i]+1+n);
       }
       for(int i=1;i<=m;i++)
       {
           int tmp;
           scanf("%d",&tmp);
           for(int j=0;j<N;j++) Sw[j][i]+=tmp;
           for(int j=1;j<=K;j++)
           {
               scanf("%d",&tmp);
               for(int w=0;w<N;w++)
               {
                   if((w&(1<<(j-1)))==0)
                   {
                       Sw[w][i]-=tmp;
                   }
                   else
                   {
                       Sw[w][i]+=tmp;
                   }
               }
           }
       }

       for(int i=0;i<N;i++)
       {
           sort(Sw[i]+1,Sw[i]+1+m);
       }
       ll ans=0;
       for(int i=0;i<N;i++)
       {
           int oth=i^(N-1);
           ans=max(Sw[i][m]+Mw[oth][n],ans);
           ans=max(Sw[oth][m]+Mw[i][n],ans);
       }
       printf("%lld\n",ans);



    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37025443/article/details/82011759
今日推荐