版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yz467796454/article/details/81950772
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;
}