hdu6435 - Problem J. CSGO - 最大曼哈顿距离
原题连接:http://acm.hdu.edu.cn/showproblem.php?pid=6435
题目大意:
有n把主武器与m把副武器,每把武器都有一个综合得分S,与k个武器参数 x[0],x[1]...x[k] ,要求你选择一把主武器与副武器,使其评估最大。评估定义为
题解:
可以看成是求 k 维上的最大曼哈顿距离。
举例,4维上,a,b两点之间的曼哈顿距离可以看成 下
的最大值,其中,比方说,
解释为 -x[0]+x[1]-x[2]+x[3] ,0表示这一维度的值符号为负,1表示这一维度的值符号为正。
之后可以先将 每个二进制状态下m把副武器的最大值求出,再求枚举 n把主武器的每个二进制状态值,求和求出最大值。
最后关于最大曼哈顿距离的推导过程,可参考https://www.cnblogs.com/lmnx/articles/2479747.html
之后AC代码:
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 100100;
const ll INF = 0x3f3f3f3f3f3f3f3f;
struct node{
ll a[10];
};
node ns[N],ms[N];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m,k;
int i,j,u;
scanf("%d%d%d",&n,&m,&k);
for(i=0;i<n;i++)
{
scanf("%lld",&ns[i].a[0]);
for(j=1;j<=k;j++)
scanf("%lld",&ns[i].a[j]);
}
for(i=0;i<m;i++)
{
scanf("%lld",&ms[i].a[0]);
ms[i].a[0] = -ms[i].a[0];
for(j=1;j<=k;j++)
scanf("%lld",&ms[i].a[j]);
}
ll ma[(1<<k)]; //副武器在 2^k 个状态下的最大值
for(i=0;i<1<<k;i++)
ma[i] = -INF;
for(i=0;i<m;i++)
{
for(j=0;j<1<<k;j++)
{
int t = j;
ll ts = 0;
ts -= ms[i].a[0];
for(u=1;u<=k;u++)
{
if(t&1)
ts += ms[i].a[u];
else
ts -= ms[i].a[u];
t = t>>1;
}
ma[j] = max(ma[j],ts);
}
}
ll ans=0;
for(i=0;i<n;i++)
{
for(j=0;j<1<<k;j++)
{
int t = j;
ll ts = 0;
ts += ns[i].a[0];
for(u=1;u<=k;u++)
{
if(t&1)
ts += ns[i].a[u];
else
ts -= ns[i].a[u];
t = t>>1;
}
ans = max(ans,ts+ma[(1<<k)-j-1]); //(第 i个主武器在 j状态下的值) + (与j对应状态下的副武器最大值)
}
}
printf("%lld\n",ans);
}
return 0;
}