2018 Multi-University Training Contest 10 1010 Problem J. CSGO(hdu6435)

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

题目链接:hdu 6435 Problem J. CSGO

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个属性,现在选一个主武器,一个副武器,要求两个武器的对应属性值的差的绝对值与s值之和最大

思路:对应两个属性值绝对值之差,|a-b|=a-b或者b-a,k小于等于5,所以两个武器的和的可能情况最多是2的k次方,32种情况。每一种状态,取n个主武器,属性和与s之和,中的最大值,与对应状态的m个副武器,属性和与s之和,中的最大值,两个最大值相加,在所有状态中取得得最大值,就是答案了。

做题的时候,思路有了,但是位运算搞得乱七八糟写不出来,要记一下:

取i的第j位是:(i>>(j-1))&1;

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;

struct node{
    int s;
    int x[10];
}a[100005],b[100005];

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m,k;
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i].s);
            for(int j=1;j<=k;j++){
                scanf("%d",&a[i].x[j]);
            }
        }
        for(int i=1;i<=m;i++){
            scanf("%d",&b[i].s);
            for(int j=1;j<=k;j++){
                scanf("%d",&b[i].x[j]);
            }
        }
        int cnt=1;
        for(int i=1;i<=k;i++){
            cnt*=2;
        }
        ll ma[35];
        for(int i=0;i<35;i++)ma[i]=-1e15;
        for(int i=0;i<cnt;i++){
            int bit[10];
            for(int j=1;j<=k;j++){
                bit[j]=(i>>(j-1))&1;//这个位运算代表取第j位 
            }
            for(int j=1;j<=n;j++){
                ll sum=0;
                sum+=a[j].s;
                for(int p=1;p<=k;p++){
                    if(bit[p]==1)sum+=a[j].x[p];
                    else sum-=a[j].x[p];
                }
                ma[i]=max(ma[i],sum);
            }
        }
        ll mb[35];
        for(int i=0;i<35;i++)mb[i]=-1e15;
        for(int i=0;i<cnt;i++){
            int bit[10];
            for(int j=1;j<=k;j++){
                bit[j]=(i>>(j-1))&1;
            }
            for(int j=1;j<=m;j++){
                ll sum=0;
                sum+=b[j].s;
                for(int p=1;p<=k;p++){
                    if(bit[p]==1)sum-=b[j].x[p];//记得取正负要反一下 
                    else sum+=b[j].x[p];
                }
                mb[i]=max(mb[i],sum);
            }
        }
        ll ans=0;
        for(int i=0;i<cnt;i++){
            ans=max(ans,ma[i]+mb[i]);
        }
        printf("%lld\n",ans);
    } 
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yz467796454/article/details/81950772