Step1 Problem:
给你n个,m维的点。
求最远的带权值的曼哈顿距离
数据范围:
2<=n<=50000, 1 <= m <= 8.
Step2 Involving algorithms:
状态压缩 && 数学
Step3 Ideas:
K-D树应该可以做,但是我们要说的是另一种方法。
把权值乘进去,题目相当于就是求最远的曼哈顿距离。
对于1维:|x1 - x2| = x1 - x2 or -x1 - (-x2)
对于2维:|x1 - x2| + |y1 - y2| = (x1+y1) - (x2 + y2) or (x1-y1) - (x2 - y2) or (-x1+y1) - (-x2 + y2) or (-x1-y1) - (-x2 - y2)
对于n维:正号为1,负号为0的话。也就是2^n个状态求最大。
Step4 Code:
#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
int a[50005][10];
int w[10];
int main()
{
int n, m;
while(~scanf("%d %d", &n, &m))
{
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
scanf("%d", &a[i][j]);
}
for(int i = 0; i < m; i++)
scanf("%d", &w[i]);
int ans = 0;
for(int k = 0; k < (1<<m); k++)
{
int Min = inf, Max = -inf;
for(int i = 0; i < n; i++)//对于每个状态 更新最大。
{
int tmp = 0;
for(int j = 0; j < m; j++)
{
if(k&(1<<j)) tmp += a[i][j] *w[j];
else tmp -= a[i][j]*w[j];
}
Min = min(tmp, Min);
Max = max(tmp, Max);
ans = max(ans, Max-Min);
}
}
printf("%d\n", ans);
}
return 0;
}