版权声明:本文为博主原创文章,转载请附上原博客链接。 https://blog.csdn.net/Dale_zero/article/details/81951412
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6435
你有n把主武器,m把副武器。现在你要各选一把。每把武器有一个基础能力值和k各参数。你需要使你的两把武器的基础值之和加各个能力值的绝对值之和最大。
先只考虑能力值:如|a1-b1|+|a2-b2|+|a3-b3|约掉绝对值之后根据a1~a3和b1~b3的值,原式的每个数字的符号有2^3种可能性。
但是只有一种符号分配的方式能使原式最大。即若a1>b1,|a1-b1|>0,如果给a1加负号原式就会小于0,不会影响最后最大值的判断。
所以枚举符号的2^k种情况,每次遍历n+m寻找最大值相加就是最后的解
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define mod 1000000007
#define For(i,m,n) for(int i=m;i<=n;i++)
#define Dor(i,m,n) for(int i=m;i>=n;i--)
#define LL long long
#define lan(a,b) memset(a,b,sizeof(a))
#define sqr(a) a*a
using namespace std;
LL a[100005][7];
LL b[100005][7];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
For(i,1,n)
{
scanf("%lld",&a[i][0]);
For(j,1,k)
scanf("%lld",&a[i][j]);
}
For(i,1,m)
{
scanf("%lld",&b[i][0]);
For(j,1,k)
scanf("%lld",&b[i][j]);
}
LL ans=0;
For(l,0,(1<<k)-1)
{
LL maxx1=-inf,maxx2=-inf;
LL sum1;
// printf("l=%d\n",l);
For(i,1,n)
{
sum1=a[i][0];
For(j,1,k)
if((l>>(j-1))&1)sum1+=a[i][j];
else sum1-=a[i][j];
//printf("a%d:sum=%d\n",i,sum1);
maxx1=max(maxx1,sum1);
//printf("maxx1=%d\n",maxx1);
}
LL sum2;
For(i,1,m)
{
sum2=b[i][0];
For(j,1,k)
if((l>>(j-1))&1)sum2-=b[i][j];
else sum2+=b[i][j];
// printf("b%d:sum2=%d\n",i,sum2);
maxx2=max(maxx2,sum2);
// printf("maxx2=%d\n",maxx2);
}
ans=max(ans,maxx1+maxx2);
}
printf("%lld\n",ans);
}
return 0;
}