版权声明:本文为博主原创文章,喜欢就点个赞吧 https://blog.csdn.net/Anxdada/article/details/81981253
传送门
题意: 有n个主武器, 和m个副武器, 每个武器有一个S, 和k个性能x[i] - x[k], (k<=5) 然后你要选择一把主武器和副武器, 让下面这个式子要尽量的大, 问最大是多少?
思路: 后面那个绝对值是不是很像曼哈顿距离的求解方法, 所以我们想到k维空间求最大曼哈顿距离(这个怎么求参考我写的另一篇博客, 就在这个专栏中, 还有板子), 然后前面那个加法怎么搞? 我们直接事先加上就行了呀. 难点在如果选的两个点是不同的集合中的, 所以我们将第一个S一个集合中点扩大inf, 另一个减小inf, 这样答案一定是在不同的集合中求到的, 最后-2*inf就是答案乐. 因为我们最后是减, 所以另一个集合我们要乘-1, 这样就满足了,. 细节请看代码:
AC Code
const ll INF = 1e15;
ll a[maxn][8];
int n, m, k;
ll cal() {
ll ans = 0, mi, mx, t;
for (int s = 0 ; s < (1<<k) ; s ++) {
mi = INF, mx = -INF;
for (int i = 1 ; i <= n+m ; i++) {
t = a[i][0];
for (int j = 1 ; j < k ; j++) { // 二进制位了好写, 还是从0开始存吧
if ((1<<j) & s) t += a[i][j];
else t -= a[i][j];
}
mi = min(mi, t);
mx = max(mx, t);
}
ans = max(ans, mx-mi);
}
return ans;
}
void solve() {
scanf("%d%d%d", &n, &m, &k); ++ k;
for (int i = 1 ; i <= n ; i++)
for (int j = 0 ; j < k ; j++) {
scanf("%lld", &a[i][j]);
if (j == 0) a[i][j] += INF;
}
for (int i = 1 ; i <= m ; i++)
for (int j = 0 ; j < k ; j++) {
scanf("%lld", &a[i+n][j]);
if (j == 0) a[i+n][j] *= -1, a[i+n][j] -= INF;
}
ll ans = cal() - 2ll*INF;
printf("%lld\n", ans);
}