題意:
有 n 個主武器和 m 個副武器,每個武器都有是 s 價值和 x[i] (i = 1...k)屬性,通過公式求出一種主武器和副武器組合的最大值。公式:
題解:
abs(x[i]-x[j]) = x[i]-x[j] 或者 x[j]-x[i] 那麼我們可以發現 x[i] 只有兩種情況,即 x[i] 和 -x[i]。最多有五個屬性,那麼組合數只有2^k,我以我們可以通過二進制來遍歷所有情況。
比如:
主武器\組合數 | 1 | 0 | 0 | 1 |
1 sum = s[1] | +x[1] | -x[1] | -x[1] | +x[1] |
2 sum = s[2] | +x[2] | -x[2] | -x[2] | +x[2] |
3 sum = s[3] | +x[3] | -x[3] | -x[3] | +x[3] |
4 sum = s[4] | +x[4] | -x[4] | -x[4] | +x[4] |
副武器\組合數 | 1 | 0 | 0 | 1 |
1 sum = s[1] | -x[1] | +x[1] | +x[1] | -x[1] |
2 sum = s[2] | -x[2] | +x[2] | +x[2] | -x[2] |
3 sum = s[3] | -x[3] | +x[3] | +x[3] | -x[3] |
4 sum = s[4] | -x[4] | +x[4] | +x[4] | -x[4] |
每種組合就取最大值,最後遍歷組合的最大值就可以了。
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <stack>
#include <cmath>
#include <deque>
#include <queue>
#include <list>
#include <set>
#include <map>
#define mem(a, b) memset(a, b, sizeof(a))
#define pi acos(-1)
using namespace std;
typedef long long ll;
const ll maxn = 1e18;
struct node{
int s;
int x[10];
}a[100010], b[100010];
int main(){
int t;
scanf("%d", &t);
while(t--){
int n, m, k;
scanf("%d %d %d", &n, &m, &k);
for(int i = 0; i < n; i++){
scanf("%d", &a[i].s);
for(int j = 0; j < k; j++){
scanf("%d", &a[i].x[j]);
}
}
for(int i = 0; i < m; i++){
scanf("%d", &b[i].s);
for(int j = 0; j < k; j++){
scanf("%d", &b[i].x[j]);
}
}
int maxx = 1 << k;
ll maxa[35];
ll maxb[35];
for(int i = 0; i < 35; i++){
maxa[i] = maxb[i] = -maxn;
}
for(int i = 0; i < maxx; i++){
for(int j = 0; j < n; j++){
ll sum = a[j].s;
for(int q = 0; q < k; q++){
if(i & (1 << q)){
sum += a[j].x[q];
}
else{
sum -= a[j].x[q];
}
}
maxa[i] = max(maxa[i], sum);
}
for(int j = 0; j < m; j++){
ll sum = b[j].s;
for(int q = 0; q < k; q++){
if(i & (1 << q)){
sum -= b[j].x[q];
}
else{
sum += b[j].x[q];
}
}
maxb[i] = max(maxb[i], sum);
}
}
ll ans = 0;
for(int i = 0; i < maxx; i++){
ans = max(ans, maxa[i]+maxb[i]);
}
printf("%lld\n", ans);
}
}