来源
2018杭电多校第十场
题意
游戏提供了 件主武器和
件副武器,每件武器有一个攻击力
,还有
个子属性
。要从武器库里面选择一件主武器和一件副武器,请选择出攻击力和及各项属性值差异和最大的两件武器。
数学表示为:
解题思路
因为需要从主武器和副武器里挑出一个。对于属性的差值,最好的方法肯定是一个最大的减去最小的。所以可以这样考虑,对于每种属性,它对答案的贡献,要么是加上它,
要么是减去它,所以只要枚举每种属性的加减状态就行,对于主武器的s,和副武器的s,也可以将他们考虑进来,只要将他们的位置错开(这样就可以保证他们不会相减了),
由于 ,也就是说主武器和副武器的各个属性前面的符号是相反的,属性数量很少,可以枚举出所有的情况选出一个最优的就是答案。
我们通过枚举子集,子集对应二进制位为1时进行加法操作,子集对应的二进制位为0时进行减法操作,来枚举每件武器采用不同的加减策略对攻击值的贡献,找到贡献最大的那两个武器。
代码
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
int a[maxn][6], b[maxn][6];
int n,m,k;
ll ans, sum;
int main() {
int t; scanf("%d",&t);
while(t--) {
ans=0; sum=0;
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<n;i++)
for(int j=0;j<=k;j++)
scanf("%d",&a[i][j]);
for(int i=0;i<m;i++)
for(int j=0;j<=k;j++)
scanf("%d",&b[i][j]);
for(int i=0;i<(1<<k);i++) {
ll mx1=-2e18, mx2=-2e18;
for(int j=0;j<n;j++) {
sum=0;
sum+=a[j][0];
for(int l=1;l<=k;l++)
if(((i>>(l-1))&1)==1) sum+=a[j][l];
else sum-=a[j][l];
mx1=max(mx1, sum);
}
for(int j=0;j<m;j++) {
sum=0;
sum+=b[j][0];
for(int l=1;l<=k;l++)
if(((i>>(l-1))&1)==1) sum-=b[j][l];
else sum+=b[j][l];
mx2=max(mx2, sum);
}
ans = max(ans, mx1+mx2);
}
printf("%lld\n",ans);
}
} 
京公网安备 11010502036488号