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

在这里插入图片描述
在这里插入图片描述
这道题,如果读懂了题意,就应该知道这里的Sample Input格式有问题;但是不影响分析;
首先我觉得很多人肯定会想到,枚举,根据题目的公式找出MW里面的最大值,然后找出SW中的最大值;就可以解决了,但是我当时始终不知道枚举,我想了一种但是1e5*1e5肯定爆;
所以这个方法行不通;之后我去百度了一下这个题,我才知道,这原来是曼哈顿最远距离的变形题;
首先应该知道什么是曼哈顿距离:比如在二维坐标中的定义:d(i,j)=|xi-xj|+|yi-yj|;在几何意义上就是:
在这里插入图片描述
这就是曼哈顿距离;但是怎么解决多维的曼哈顿距离呢?
首先解决什么是多维:
我们二维坐标是不是(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)有下面四种取值形式:
在这里插入图片描述
但是哪一个最大呢?当然枚举去判断咯;
上面的形式可以发现x1和x2的系数都是相同的(+,-好都一样),同理可知:y1和y2的也是一样的;
这点说明了什么呢?说明我可以用0表示负号,1表示正号,也就是说:
在这里插入图片描述
可以发现都是从00—11的,然后来枚举每种状态,因为两个的点的x,y对应的状态都是相同的;
那么多维就可以类比思考;
好了,到这里这道题就解决了一大半了;
那么怎么枚举状态呢?其实如果写过用位运算求子集的应该可以想到用两个for就可以枚举出所有的状态;
这样就把本属于类的枚举转化为了一类中自己的枚举了;这样时间复杂度就成了O(2n)了;
AC代码(只不过这道题换成了n+m个k维的点了,每次枚举同一状态的最大值):

#include<bits/stdc++.h>
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<n;i++){//初始化第一个 
		  	  scanf("%lld",&M1[i].s);//这里用结构体跟上
		  	  for(int j=0;j<k;j++){
		  	  	    scanf("%lld",&M1[i].a[j]);
				}
		  } 
		    for(int i=0;i<m;i++){//初始化第二个 
		  	  scanf("%lld",&M2[i].s);//同理结构体跟上
		  	  for(int j=0;j<k;j++){
		  	  	    scanf("%lld",&M2[i].a[j]);
				}
		  }
	  ll ans1=-INF,ans2=-INF;
	  ll ans=0;
		  for(int i=0;i<(1<<k);i++){//枚举每种对应的状态 比如 00   01  10  11这四个(把它想为二进制就好理解了)
		  	ans1=-INF,ans2=-INF;//这里注意每次都要设为-INF因为这样才能保证每次的枚举不会被上次的影响
		    for(int j=0;j<n;j++){//计算主武器,在同一状态下的最大值
		    	ll temp=0;
		  	    for(int p=0;p<k;p++){//这里就很巧妙了,利用p位移1并且能表示a[]对应的下标
		  	    	if(i&(1<<p)) temp+=M1[j].a[p];//判断是不是1;
		  	    	else temp-=M1[j].a[p];
		    		  }
				  ans1=max(ans1,temp+M1[j].s);
		    }
		    for(int j=0;j<m;j++){//计算副武器,在同一状态下的最大值
		    	  ll temp=0;
		    	  for(int p=0;p<k;p++){//这里也很巧妙
		    	  	if(i&(1<<p)) temp+=M2[j].a[p];//判断是不是1;
		    	  	else temp-=M2[j].a[p];
				  }
				  ans2=max(ans2,-temp+M2[j].s);//去最大值
			}
			ans=max(ans,ans1+ans2);
	    }
	    printf("%lld\n",ans);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.项目代码功能经验证ok,确保稳定可靠运行。欢迎下载使用! 2.主要针对各个计算机相关专业,包括计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网等领域的在校学生、专业教师或企业员工使用。 3.项目具有丰富的拓展空间,不仅可作为入门进阶,也可直接作为毕设、课程设计、大作业、初期项目立项演示等用途。 4.当然也鼓励大家基于此进行二次开发。在使用过程中,如有问题或建议,请及时私信沟通。 5.期待你能在项目中找到乐趣和灵感,也欢迎你的分享和反馈! 【资源说明】 基于Nodejs+oicq库的CSgo平台数据查询机器人源码+项目说明.zip 基于nodejs于oicq库的csgo完美平台数据查询机器人 目前有一些乱七八糟的功能,比如数据查询(武器,胜率,等等)已经完美平台封禁情况 还可以查看热门比赛赛程 当然还有随机二次元图片点歌功能 还有ai对话等等 主要开始使用时候要修改的有config目录中csgo和bot文件夹中内容 需要ffmpeg才能使用ai与点歌功能 bilibili直播提醒于2023/1/24完成 bilibili开播提醒默认关闭插件,开启请阅读index.js注释 官匹数据查询于2023/1/21完成 csgo资讯推送已于2023/4/29完成 csgo资讯推送默认关闭插件,开启请阅读index.js注释 5e定级赛刚打完准备开始着手写啦,目前还是鸽子 buff方面的饰品查询于2023/2/1完成

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值