Problem J. CSGO(K维曼哈顿最大距离+二进制状态压缩(或者叫枚举二进制))

Problem J. CSGO(K维曼哈顿最大距离+二进制状态压缩(或者叫枚举二进制))_第1张图片
Problem J. CSGO(K维曼哈顿最大距离+二进制状态压缩(或者叫枚举二进制))_第2张图片
这道题,如果读懂了题意,就应该知道这里的Sample Input格式有问题;但是不影响分析;
首先我觉得很多人肯定会想到,枚举,根据题目的公式找出MW里面的最大值,然后找出SW中的最大值;就可以解决了,但是我当时始终不知道枚举,我想了一种但是1e5*1e5肯定爆;
所以这个方法行不通;之后我去百度了一下这个题,我才知道,这原来是曼哈顿最远距离的变形题;
首先应该知道什么是曼哈顿距离:比如在二维坐标中的定义:d(i,j)=|xi-xj|+|yi-yj|;在几何意义上就是:
Problem J. CSGO(K维曼哈顿最大距离+二进制状态压缩(或者叫枚举二进制))_第3张图片
这就是曼哈顿距离;但是怎么解决多维的曼哈顿距离呢?
首先解决什么是多维:
我们二维坐标是不是(xi,yi)?三位坐标是不是(xi,yi,zi)?;那么多维我们就可以用代数形式表示为:
(x1,x2,x3,x4…xn);这就是多维上的坐标形式,只是这里的y,z写成了x2,x3的形式,所它们的本质是一样滴;(注意这里是n维的一个点)
那么这道题的后面这一坨:在这里插入图片描述
不就是k维的曼哈顿距离吗?因为对于主武器Swm对应一个k维的点;所以我们在枚举的时候只需要让它们在逻辑上产生联系(其实用一个结构体就OK了或者再开别的数组);
那么怎么计算k维最大的曼哈顿距离呢?
想来看这个:我可以知道,对于二维的曼哈顿定义形式,如:
d(1,2)=|x1-x2|+|y1-y2|;可以经过下面四种讨论,我就可以把绝对值去掉:
1.如果x1-x2为正 && y1-y2为正数 那么d(1,2)=x1-x2+y1-y2;
2.如果x1-x2为正&& y1-y2为负数 那么d(1,2)=x1-x2+y2-y1;
3.如果x1-x2为负&&y1-y2为正数 那么d(1,2)=x2-x1+y1-y2;
4.如果x1-x2为负&&y-1-y2为负数 那么d(1,2)=x2-x1+y2-y1;
那么二维上的两个点之间的曼哈顿距离就只有这四种形式:
然后我们把x1和y1放在一起,x2和y2放在一起可以知道d(1,2)有下面四种取值形式:
Problem J. CSGO(K维曼哈顿最大距离+二进制状态压缩(或者叫枚举二进制))_第4张图片
但是哪一个最大呢?当然枚举去判断咯;
上面的形式可以发现x1和x2的系数都是相同的(+,-好都一样),同理可知:y1和y2的也是一样的;
这点说明了什么呢?说明我可以用0表示负号,1表示正号,也就是说:
Problem J. CSGO(K维曼哈顿最大距离+二进制状态压缩(或者叫枚举二进制))_第5张图片
可以发现都是从00—11的,然后来枚举每种状态,因为两个的点的x,y对应的状态都是相同的;
那么多维就可以类比思考;
好了,到这里这道题就解决了一大半了;
那么怎么枚举状态呢?其实如果写过用位运算求子集的应该可以想到用两个for就可以枚举出所有的状态;
这样就把本属于类的枚举转化为了一类中自己的枚举了;这样时间复杂度就成了O(2n)了;
AC代码(只不过这道题换成了n+m个k维的点了,每次枚举同一状态的最大值):

#include
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
#define INF 0x3f3f3f3f
struct MM{
	ll a[20];
	ll s;
}M1[maxn],M2[maxn];//两个结构体数组
int main(){
	ll T,n,m,k;
	scanf("%lld",&T);
	while(T--){
		  scanf("%lld %lld %lld",&n,&m,&k);
		  for(int i=0;i

你可能感兴趣的:(数学几何)