HDU 6435(状态压缩)

传送门

题面:

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个主武器和n个副武器,每个武器都有k个参数以及一个数S,让你从中选取一个主武器和一个服务器,使得最大。

题目分析:

    首先,如果上面的式子中没有绝对值的话,这道题将会非常简单,我们只需要分别求出,并去主武器的最大值以及副武器的最小值即为答案。

    但是这个题的难点就是在于处理绝对值上。因此我们考虑将绝对值拆开。不难发现,根据绝对值的性质有:

    

    因此我们发现,对于每一个主武器,他的每一种参数都会存在着加或减两种状态,此时我们会发现,每一种武器的这么些个状态最多只有个,即32种。因此我们大可用状态压缩,用一个二进制数表示当前参数的状态,并不断的枚举k位二进制数i,令Xmw[i]为处于第i种状态时主武器的最大值,Xsm[i]为处于第i种状态时副武器的最大值。如果第j位为0,则我们将第j个参数相加,如果第j位为1,则将第j个参数相减。并不断的对他们分别取最大值,这样我们就可以将主武器的和副武器的的所有不同的情况的最大值都枚举出来了。

    之后我们只需要枚举出所有的主武器和副武器的状态相反的情况(主副武器一加一减),并最后取个最大值即为答案。

    PS:因为在这个题中主副武器的值都可能存在负数的情况,因此我们需要将主副武器的初值均赋为-INF才行。

代码:

#include <bits/stdc++.h>
#define maxn 100005
using namespace std;
typedef long long ll;
ll MW[40],SW[40];
ll tmp[8];
const ll INF=0x3f3f3f3f3f3f3f3f;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m,k;
        scanf("%d%d%d",&n,&m,&k);
        for(int i=0;i<40;i++){//初始化,注意必须得赋值为-INF
            MW[i]=-INF;
            SW[i]=-INF;
        }
        for(int i=0;i<n;i++){
            ll val;
            scanf("%lld",&val);
            for(int j=0;j<k;j++){
                scanf("%lld",&tmp[j]);//输入第i个主武器的k个参数
            }
            for(int j=0;j<(1<<k);j++){//用状态压缩枚举出2^k种状态
                ll cnt=val;
                for(int t=0;t<k;t++){//如果第t位为1,则加,否则相减
                    if((j>>t)&1) cnt+=tmp[t];
                    else cnt-=tmp[t];
                }
                MW[j]=max(MW[j],cnt);//不断记录主武器在处于当前j状态下的最大值
            }
        }
        for(int i=0;i<m;i++){//副武器同理
            ll val;
            scanf("%lld",&val);
            for(int j=0;j<k;j++){
                scanf("%lld",&tmp[j]);
            }
            for(int j=0;j<(1<<k);j++){
                ll cnt=val;
                for(int t=0;t<k;t++){
                    if((j>>t)&1) cnt+=tmp[t];
                    else cnt-=tmp[t];
                }
                SW[j]=max(SW[j],cnt);
            }
        }
        ll maxx=-INF;
        for(int i=0;i<(1<<k);i++){//枚举出主武器和副武器中状态相反的状态
            maxx=max(maxx,MW[i]+SW[(1<<k)-1-i]);
        }
        cout<<maxx<<endl;
    }
}

 

posted @ 2018-08-23 09:11  ChenJr  阅读(156)  评论(0编辑  收藏  举报