求取一对符合要求的数(前后夹击,直至相遇)

本文介绍了一种高效算法,用于从大量整数中找出和为特定值的整数对。通过排序和双指针技术,实现O(nlogn)的时间复杂度,适用于竞赛和实际应用。

07: 和为给定数

描述:
给出若干个整数,询问其中是否有一对数的和等于给定的数。

输入:
共三行:
第一行是整数n(0 < n <= 100,000),表示有n个整数。
第二行是n个整数。整数的范围是在0到10^8之间。
第三行是一个整数m(0 <= m <= 2^30),表示需要得到的和。

输出:
若存在和为m的数对,输出两个整数,小的在前,大的在后,中间用单个空格隔开。若有多个数对满足条件,选择数对中较小的数更小的。若找不到符合要求的数对,输出一行No。

样例输入:
4
2 5 1 4
6

样例输出:
1 5

解法1:(二分查找)

  1. 将数组排序,复杂度是O(n×log(n))
  2. 查找的时候,设置两个变量i和j,i初值是0,j初值是n-1.看a[i]+a[j],如果大于m,就让j
    减1,如果小于m,就让i加1,直至a[i]+a[j]=m。
    这种解法总的复杂度是O(n×log(n))的。

解法2:(相对更快)

  1. 将数组排序,复杂度是O(n×log(n))
  2. 查找的时候,设置两个变量i和j,i初值是0,j初值是n-1.看a[i]+a[j],如果大于m,就让j
    减1,如果小于m,就让i加1,直至a[i]+a[j]=m。
    这种解法总的复杂度是O(n×log(n))的。

代码如下:

#include <iostream>
#include <cstdio>  
#include <algorithm> 
constexpr auto eps = 1E-6; 
using namespace std; 

int main()
{ 
	long long n, a[100010], m;
 	cin >> n;
	for (int i = 0; i < n; ++i) 
		cin >> a[i];
	cin >> m;
	sort(a, a + n);

	long long p = 0, q = n - 1;
	bool exist = false;  
	while (p!=q) {
		if (a[p] + a[q] == m) {
			exist = true;
			cout << a[p] << " " << a[q];
			break;
		} 
		else if (a[p] + a[q] < m)
			++p;
		else
			--q;
	}
	if (!exist)
		cout << "No"; 
	return 0;
}
<think>我们需要解决两个主要问题: 1. 英雄在攻击状态下也能转向,以应对被两个怪兽夹击的情况。 2. 英雄在解决完最近的怪兽后,自动判断距离其他怪兽的距离,如果在攻击范围内,则直接转向并攻击下一个怪兽。 ### 解决方案: #### 1. 英雄在攻击状态下也能转向 - 修改逻辑:在英雄攻击状态下,根据最近的怪兽位置调整英雄朝向。 - 在`update`方法中,即使英雄处于攻击状态,也要根据最近的怪兽位置更新朝向。 #### 2. 英雄攻击完一个怪兽后自动攻击下一个 - 当当前攻击目标(最近的怪兽)死亡或超出攻击范围时,重新寻找下一个最近的怪兽。 - 在`checkHeroAttack`方法中,如果当前目标无效(死亡或超出范围),则重新寻找目标。 ### 具体修改: #### 修改点1:在攻击状态下更新英雄朝向 在`GameManager`的`update`方法中,无论英雄处于什么状态(包括攻击状态),只要最近怪兽存在,就更新英雄朝向。 但是注意:攻击动画播放时,英雄应该面向当前的攻击目标(即最近的怪兽)。因此,在攻击状态下,我们也需要根据怪兽的位置更新朝向。 我们可以在`checkMonstersHurt`方法之前,或者单独在攻击状态时更新朝向。这里选择在`update`方法中,每次循环都根据最近怪兽的位置更新英雄朝向(即使攻击状态也更新)。 然而,在攻击状态下,英雄的位置不会移动,但怪兽可能会移动(比如另一个怪兽从背后攻击),所以我们需要在攻击状态下也调整英雄朝向以面对当前攻击目标。 修改`update`方法,在攻击状态下也调用`updateHeroDirection`,但方向如何确定?我们可以根据最近怪兽相对于英雄的位置来确定。 在`GameManager`中添加一个方法,用于根据最近怪兽的位置更新英雄朝向(在攻击状态时调用): ```typescript // 在攻击状态下更新英雄朝向(面向最近的怪兽) private updateHeroDirectionForAttack() { if (!this.nearestMonsterForHero) return; const heroPos = this.HeroNode.position; const monsterPos = this.nearestMonsterForHero.position; // 计算方向:怪兽在英雄的左边还是右边 const directionX = monsterPos.x - heroPos.x; // 调用现有的更新朝向方法 this.updateHeroDirection(directionX); } ``` 然后在`update`方法中,当英雄处于攻击状态时,调用这个方法: ```typescript update(deltaTime: number) { // ... 其他代码 ... // 在攻击状态下更新英雄朝向(面向最近的怪兽) if (this.isHeroAttack && this.nearestMonsterForHero) { this.updateHeroDirectionForAttack(); } // ... 检测怪兽受伤状态等 ... } ``` #### 修改点2:英雄攻击完一个怪兽后自动攻击下一个 在`checkHeroAttack`方法中,我们需要检查当前最近怪兽是否已经死亡或者超出攻击范围。如果已经死亡或者超出攻击范围,则重新寻找最近怪兽,并判断是否可以直接攻击。 修改`checkHeroAttack`方法: ```typescript private checkHeroAttack() { // 英雄死亡时不能攻击 if (this.isHeroDied) { return; } // 如果当前最近怪兽无效(死亡、被移除等),则重新寻找 if (!this.nearestMonsterForHero || !this.nearestMonsterForHero.isValid) { this.findNearestMonsterForHero(); // 如果重新寻找后还是没有怪兽,则站立 if (!this.nearestMonsterForHero) { this.setHeroStand(); return; } } // 检查攻击冷却时间 if (this.heroAttackTimer < this.heroAttackCooldown) { return; } // 计算与最近怪兽的距离 const heroPos = this.HeroNode.position; const monsterPos = this.nearestMonsterForHero.position; const distance = Vec3.distance(heroPos, monsterPos); // 获取怪兽尺寸 const controller = this.nearestMonsterForHero.getComponent(MonsterController); if (!controller || controller.isDie) { // 如果怪兽已经死亡,重新寻找最近怪兽 this.findNearestMonsterForHero(); // 如果重新寻找后还是没有怪兽,则站立 if (!this.nearestMonsterForHero) { this.setHeroStand(); return; } // 重新计算新目标的距离 const newMonsterPos = this.nearestMonsterForHero.position; const newDistance = Vec3.distance(heroPos, newMonsterPos); const newController = this.nearestMonsterForHero.getComponent(MonsterController); if (!newController || newController.isDie) { this.setHeroStand(); return; } const monsterSize = newController.MonsterSize; const yDiff = Math.abs(heroPos.y - newMonsterPos.y); // 如果新目标在攻击范围内 if (newDistance <= this.heroAttackRange + monsterSize && yDiff <= 20) { this.setHeroAttack(); } return; } const monsterSize = controller.MonsterSize; const yDiff = Math.abs(heroPos.y - monsterPos.y); // 如果距离在攻击范围内且Y轴差不超过20像素 if (distance <= this.heroAttackRange + monsterSize && yDiff <= 20) { // 设置英雄为攻击状态 this.setHeroAttack(); } else { // 如果不在攻击范围内,则重新寻找最近怪兽 this.findNearestMonsterForHero(); // 如果重新寻找后没有怪兽,则站立 if (!this.nearestMonsterForHero) { this.setHeroStand(); } } } ``` ### 完整修改后的代码: 由于代码较长,这里只给出修改的关键部分。注意,我们添加了`updateHeroDirectionForAttack`方法,并在`update`中调用,同时修改了`checkHeroAttack`方法。 #### 1. 添加`updateHeroDirectionForAttack`方法: ```typescript // 在攻击状态下更新英雄朝向(面向最近的怪兽) private updateHeroDirectionForAttack() { if (!this.nearestMonsterForHero || !this.nearestMonsterForHero.isValid) return; const heroPos = this.HeroNode.position; const monsterPos = this.nearestMonsterForHero.position; // 计算方向:怪兽在英雄的左边还是右边 const directionX = monsterPos.x - heroPos.x; // 调用现有的更新朝向方法(注意:这里传入的是方向向量X分量,不需要归一化,因为我们只需要正负) this.updateHeroDirection(directionX); } ``` #### 2. 修改`update`方法,在攻击状态时更新朝向: ```typescript update(deltaTime: number) { // ... 原有代码 ... // 在攻击状态下更新英雄朝向(面向最近的怪兽) if (this.isHeroAttack && this.nearestMonsterForHero) { this.updateHeroDirectionForAttack(); } // ... 原有代码 ... } ``` #### 3. 修改`checkHeroAttack`方法(如上所示,注意处理怪兽死亡和重新寻找的逻辑) ### 注意事项: - 在攻击状态下更新英雄朝向,确保英雄始终面向当前的攻击目标(最近的怪兽)。 - 当当前攻击目标死亡时,立即寻找下一个最近的目标,如果下一个目标在攻击范围内,则直接攻击,无需移动。 这样修改后,英雄在攻击状态下也能转向,并且攻击完一个怪兽后会立即转向并攻击下一个在攻击范围内的怪兽。 §§相关问题§§: 1. 如何优化游戏中大量怪兽的寻敌性能? 2. 在多人游戏中如何同步角色的攻击方向和目标选择? 3. 如何实现英雄的连击机制? 4. 如何处理多个怪兽同时攻击英雄时的优先级(如仇恨系统)?</think>为了增强英雄的灵活性和战斗表现,我将实现以下改进: 1. 在攻击状态下允许英雄转向 2. 击败当前目标后自动转向并攻击最近的怪兽 3. 优化攻击检测逻辑 以下是完整的修改方案: ```typescript // GameManager.ts import { _decorator, Component, instantiate, Node, Prefab, Vec3, v3, Animation, sp } from 'cc'; const { ccclass, property } = _decorator; import { MonsterController } from './MonsterController'; @ccclass('GameManager') export class GameManager extends Component { // ... [其他代码保持不变] ... // 新增方法:在攻击状态下更新英雄朝向 private updateHeroDirectionInAttack() { if (!this.nearestMonsterForHero) return; const heroPos = this.HeroNode.position; const monsterPos = this.nearestMonsterForHero.position; // 计算方向:怪兽在英雄的左边还是右边 const directionX = monsterPos.x - heroPos.x; // 调用现有的更新朝向方法 this.updateHeroDirection(directionX); } /** * 检测英雄是否可以攻击(增强) */ private checkHeroAttack() { // 英雄死亡时不能攻击 if (this.isHeroDied) { return; } // 如果当前目标无效,尝试重新寻找目标 if (!this.nearestMonsterForHero || !this.nearestMonsterForHero.isValid) { this.findNearestMonsterForHero(); if (!this.nearestMonsterForHero) { this.setHeroStand(); return; } } // 检查攻击冷却时间 if (this.heroAttackTimer < this.heroAttackCooldown) { return; } // 获取当前目标的控制器 const controller = this.nearestMonsterForHero.getComponent(MonsterController); if (!controller || controller.isDie) { // 如果当前目标已死亡,重新寻找目标 this.findNearestMonsterForHero(); if (!this.nearestMonsterForHero) { this.setHeroStand(); return; } } // 计算与最近怪兽的距离 const heroPos = this.HeroNode.position; const monsterPos = this.nearestMonsterForHero.position; const distance = Vec3.distance(heroPos, monsterPos); // 获取怪兽尺寸 const monsterController = this.nearestMonsterForHero.getComponent(MonsterController); if (!monsterController) return; const monsterSize = monsterController.MonsterSize; // 计算Y轴坐标差 const yDiff = Math.abs(heroPos.y - monsterPos.y); // 如果距离在攻击范围内且Y轴差不超过20像素 if (distance <= this.heroAttackRange + monsterSize && yDiff <= 20) { // 设置英雄为攻击状态 this.setHeroAttack(); } else { // 如果不在攻击范围内,重新寻找目标 this.findNearestMonsterForHero(); // 如果新目标在攻击范围内,直接攻击 if (this.nearestMonsterForHero) { const newMonsterPos = this.nearestMonsterForHero.position; const newDistance = Vec3.distance(heroPos, newMonsterPos); const newYDiff = Math.abs(heroPos.y - newMonsterPos.y); const newMonsterSize = this.nearestMonsterForHero.getComponent(MonsterController)?.MonsterSize || 0; if (newDistance <= this.heroAttackRange + newMonsterSize && newYDiff <= 20) { this.setHeroAttack(); } } } } // 更新方法 update(deltaTime: number) { // ... [其他代码保持不变] ... // 在攻击状态下更新英雄朝向 if (this.isHeroAttack && this.nearestMonsterForHero) { this.updateHeroDirectionInAttack(); } // ... [其他代码保持不变] ... } // ... [其他代码保持不变] ... } ``` ### 修改点解释: 1. **在攻击状态下允许英雄转向**: ```typescript private updateHeroDirectionInAttack() { if (!this.nearestMonsterForHero) return; const heroPos = this.HeroNode.position; const monsterPos = this.nearestMonsterForHero.position; // 计算方向:怪兽在英雄的左边还是右边 const directionX = monsterPos.x - heroPos.x; // 调用现有的更新朝向方法 this.updateHeroDirection(directionX); } ``` - 新增方法专门处理攻击状态下的转向 - 根据当前目标怪兽的位置计算转向方向 - 在`update`方法中调用此方法:`if (this.isHeroAttack) this.updateHeroDirectionInAttack();` 2. **击败当前目标后自动转向并攻击最近的怪兽**: ```typescript private checkHeroAttack() { // ... [其他代码] ... // 获取当前目标的控制器 const controller = this.nearestMonsterForHero.getComponent(MonsterController); if (!controller || controller.isDie) { // 如果当前目标已死亡,重新寻找目标 this.findNearestMonsterForHero(); if (!this.nearestMonsterForHero) { this.setHeroStand(); return; } } // ... [其他代码] ... if (distance <= this.heroAttackRange + monsterSize && yDiff <= 20) { this.setHeroAttack(); } else { // 如果不在攻击范围内,重新寻找目标 this.findNearestMonsterForHero(); // 如果新目标在攻击范围内,直接攻击 if (this.nearestMonsterForHero) { // 检查新目标是否在攻击范围内 if (newDistance <= this.heroAttackRange + newMonsterSize && newYDiff <= 20) { this.setHeroAttack(); } } } } ``` - 在攻击检测中增加目标有效性检查 - 如果当前目标死亡或无效,立即寻找新目标 - 如果新目标在攻击范围内,直接发起攻击 3. **优化攻击状态管理**: ```typescript private setHeroAttack() { if (this._isHeroDied) return; // 重置其他状态 this._isHeroAttack = true; this._isHeroStand = false; // 随机选择攻击动画 const attackAnimations = ['m_attack_1_a', 'm_attack_2_a']; const randomAttack = attackAnimations[Math.floor(Math.random() * attackAnimations.length)]; // 播放攻击动画 this.playHeroAnimation(randomAttack); // 重置攻击计时器 this.heroAttackTimer = 0; // 立即更新朝向以面向目标 if (this.nearestMonsterForHero) { this.updateHeroDirectionInAttack(); } } ``` - 在设置攻击状态时立即更新朝向 - 确保英雄在开始攻击时就面向目标 ### 完整修改后的`GameManager.ts`文件: <details> <summary>点击查看完整 GameManager.ts</summary> ```typescript // GameManager.ts import { _decorator, Component, instantiate, Node, Prefab, Vec3, v3, Animation, sp } from 'cc'; const { ccclass, property } = _decorator; import { MonsterController } from './MonsterController'; @ccclass('GameManager') export class GameManager extends Component { // ... [其他代码保持不变] ... // 新增方法:在攻击状态下更新英雄朝向 private updateHeroDirectionInAttack() { if (!this.nearestMonsterForHero) return; const heroPos = this.HeroNode.position; const monsterPos = this.nearestMonsterForHero.position; // 计算方向:怪兽在英雄的左边还是右边 const directionX = monsterPos.x - heroPos.x; // 调用现有的更新朝向方法 this.updateHeroDirection(directionX); } /** * 检测英雄是否可以攻击(增强) */ private checkHeroAttack() { // 英雄死亡时不能攻击 if (this.isHeroDied) { return; } // 如果当前目标无效,尝试重新寻找目标 if (!this.nearestMonsterForHero || !this.nearestMonsterForHero.isValid) { this.findNearestMonsterForHero(); if (!this.nearestMonsterForHero) { this.setHeroStand(); return; } } // 检查攻击冷却时间 if (this.heroAttackTimer < this.heroAttackCooldown) { return; } // 获取当前目标的控制器 const controller = this.nearestMonsterForHero.getComponent(MonsterController); if (!controller || controller.isDie) { // 如果当前目标已死亡,重新寻找目标 this.findNearestMonsterForHero(); if (!this.nearestMonsterForHero) { this.setHeroStand(); return; } } // 计算与最近怪兽的距离 const heroPos = this.HeroNode.position; const monsterPos = this.nearestMonsterForHero.position; const distance = Vec3.distance(heroPos, monsterPos); // 获取怪兽尺寸 const monsterController = this.nearestMonsterForHero.getComponent(MonsterController); if (!monsterController) return; const monsterSize = monsterController.MonsterSize; // 计算Y轴坐标差 const yDiff = Math.abs(heroPos.y - monsterPos.y); // 如果距离在攻击范围内且Y轴差不超过20像素 if (distance <= this.heroAttackRange + monsterSize && yDiff <= 20) { // 设置英雄为攻击状态 this.setHeroAttack(); } else { // 如果不在攻击范围内,重新寻找目标 this.findNearestMonsterForHero(); // 如果新目标在攻击范围内,直接攻击 if (this.nearestMonsterForHero) { const newMonsterPos = this.nearestMonsterForHero.position; const newDistance = Vec3.distance(heroPos, newMonsterPos); const newYDiff = Math.abs(heroPos.y - newMonsterPos.y); const newMonsterSize = this.nearestMonsterForHero.getComponent(MonsterController)?.MonsterSize || 0; if (newDistance <= this.heroAttackRange + newMonsterSize && newYDiff <= 20) { this.setHeroAttack(); } } } } /** * 设置英雄攻击状态 */ private setHeroAttack() { if (this._isHeroDied) return; // 重置其他状态 this._isHeroAttack = true; this._isHeroStand = false; // 随机选择攻击动画 const attackAnimations = ['m_attack_1_a', 'm_attack_2_a']; const randomAttack = attackAnimations[Math.floor(Math.random() * attackAnimations.length)]; // 播放攻击动画 this.playHeroAnimation(randomAttack); // 重置攻击计时器 this.heroAttackTimer = 0; // 立即更新朝向以面向目标 if (this.nearestMonsterForHero) { this.updateHeroDirectionInAttack(); } } // 更新方法 update(deltaTime: number) { // ... [其他代码保持不变] ... // 在攻击状态下更新英雄朝向 if (this.isHeroAttack && this.nearestMonsterForHero) { this.updateHeroDirectionInAttack(); } // ... [其他代码保持不变] ... } // ... [其他代码保持不变] ... } ``` </details> ### 改进效果说明: 1. **灵活转向**: - 英雄在攻击状态下也能根据目标位置调整朝向 - 解决了被多个怪兽包围时的转向问题 2. **连续战斗**: - 击败当前目标后自动寻找下一个目标 - 如果新目标在攻击范围内,立即发起攻击 - 无需移动即可转向并攻击不同方向的敌人 3. **战斗流畅性**: - 攻击开始时立即转向目标 - 目标切换逻辑更智能,减少无效移动 - 提高战斗节奏和流畅度 ### 流程图说明: ```mermaid graph TD A[英雄攻击状态] --> B{当前目标有效?} B -->|是| C[攻击目标] B -->|否| D[寻找新目标] D --> E{找到新目标?} E -->|是| F{新目标在攻击范围?} F -->|是| G[攻击新目标] F -->|否| H[移动或站立] E -->|否| I[站立] C --> J[攻击结束] J --> K{目标是否死亡?} K -->|是| D K -->|否| C ``` 这个改进使英雄在战斗中的表现更加灵活智能,能够有效应对被多个敌人包围的情况,提供更流畅的战斗体验。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值