CodeForces 514B Han Solo and Lazer Gun

此编程问题探讨了汉索罗使用激光枪消灭战场上的帝国风暴兵所需的最少射击次数。战场采用笛卡尔坐标系,汉索罗位于特定点上,可以沿着通过该点的任意直线射击。任务是确定消灭所有风暴兵所需的最小射击次数。
B. Han Solo and Lazer Gun
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

There are n Imperial stormtroopers on the field. The battle field is a plane with Cartesian coordinate system. Each stormtrooper is associated with his coordinates(x, y) on this plane.

Han Solo has the newest duplex lazer gun to fight these stormtroopers. It is situated at the point(x0, y0). In one shot it can can destroy all the stormtroopers, situated on some line that crosses point(x0, y0).

Your task is to determine what minimum number of shots Han Solo needs to defeat all the stormtroopers.

The gun is the newest invention, it shoots very quickly and even after a very large number of shots the stormtroopers don't have enough time to realize what's happening and change their location.

Input

The first line contains three integers n,x0 и y0 (1 ≤ n ≤ 1000, - 104 ≤ x0, y0 ≤ 104) — the number of stormtroopers on the battle field and the coordinates of your gun.

Next n lines contain two integers each xi, yi ( - 104 ≤ xi, yi ≤ 104) — the coordinates of the stormtroopers on the battlefield. It is guaranteed that no stormtrooper stands at the same point with the gun. Multiple stormtroopers can stand at the same point.

Output

Print a single integer — the minimum number of shots Han Solo needs to destroy all the stormtroopers.

Examples
Input
4 0 0
1 1
2 2
2 0
-1 -1
Output
2
Input
2 1 2
1 1
1 0
Output
1
Note

Explanation to the first and second samples from the statement, respectively:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;

double a[1010];

int main(){
    int n,i,x,y;
    int xx,yy;
    int cnt,res;
    int flag;
    while(~scanf("%d %d %d",&n,&x,&y)){
    	cnt=res=0;
     	flag=0;
        for(i=0;i<n;i++){
            scanf("%d %d",&xx,&yy);
            double jx=xx-x;
            double jy=yy-y;
            if(!flag&&jx==0){
                flag=1;
                res++;
            }
            else if(jx!=0){
                a[cnt++]=jy/jx;
            }
        }
        sort(a,a+cnt);
        for(i=0;i<cnt;i++){
        	while(a[i]==a[i+1]&&i<cnt){
	        	i++;
	        }	
        	res++;
        }
        printf("%d\n",res);
    }
    return 0;
}		  	 	



【无人机】基于改进粒子群算法的无人机路径规划研究[和遗传算法、粒子群算法进行比较](Matlab代码实现)内容概要:本文围绕基于改进粒子群算法的无人机路径规划展开研究,重点探讨了在复杂环境中利用改进粒子群算法(PSO)实现无人机三维路径规划的方法,并将其与遗传算法(GA)、标准粒子群算法等传统优化算法进行对比分析。研究内容涵盖路径规划的多目标优化、避障策略、航路点约束以及算法收敛性和寻优能力的评估,所有实验均通过Matlab代码实现,提供了完整的仿真验证流程。文章还提到了多种智能优化算法在无人机路径规划中的应用比较,突出了改进PSO在收敛速度和全局寻优方面的优势。; 适合人群:具备一定Matlab编程基础和优化算法知识的研究生、科研人员及从事无人机路径规划、智能优化算法研究的相关技术人员。; 使用场景及目标:①用于无人机在复杂地形或动态环境下的三维路径规划仿真研究;②比较不同智能优化算法(如PSO、GA、蚁群算法、RRT等)在路径规划中的性能差异;③为多目标优化问题提供算法选型和改进思路。; 阅读建议:建议读者结合文中提供的Matlab代码进行实践操作,重点关注算法的参数设置、适应度函数设计及路径约束处理方式,同时可参考文中提到的多种算法对比思路,拓展到其他智能优化算法的研究与改进中。
标题中的"EthernetIP-master.zip"压缩文档涉及工业自动化领域的以太网通信协议EtherNet/IP。该协议由罗克韦尔自动化公司基于TCP/IP技术架构开发,已广泛应用于ControlLogix系列控制设备。该压缩包内可能封装了协议实现代码、技术文档或测试工具等核心组件。 根据描述信息判断,该资源主要用于验证EtherNet/IP通信功能,可能包含测试用例、参数配置模板及故障诊断方案。标签系统通过多种拼写形式强化了协议主题标识,其中"swimo6q"字段需结合具体应用场景才能准确定义其技术含义。 从文件结构分析,该压缩包采用主分支命名规范,符合开源项目管理的基本特征。解压后预期可获取以下技术资料: 1. 项目说明文档:阐述开发目标、环境配置要求及授权条款 2. 核心算法源码:采用工业级编程语言实现的通信协议栈 3. 参数配置文件:预设网络地址、通信端口等连接参数 4. 自动化测试套件:包含协议一致性验证和性能基准测试 5. 技术参考手册:详细说明API接口规范与集成方法 6. 应用示范程序:展示设备数据交换的标准流程 7. 工程构建脚本:支持跨平台编译和部署流程 8. 法律声明文件:明确知识产权归属及使用限制 该测试平台可用于构建协议仿真环境,验证工业控制器与现场设备间的数据交互可靠性。在正式部署前开展此类测试,能够有效识别系统兼容性问题,提升工程实施质量。建议用户在解压文件后优先查阅许可协议,严格遵循技术文档的操作指引,同时需具备EtherNet/IP协议栈的基础知识以深入理解通信机制。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
<think> 题目链接:https://codeforces.com/problemset/problem/519/B 题目大意:给出n个数字,然后给出n-1个数字(第一组),再给出n-2个数字(第二组)。第一组是原数组去掉一个元素,第二组是第一组再去掉一个元素。求被去掉的两个元素(按顺序,即第一个被去掉的是第一个答案,第二个被去掉的是第二个答案)。 方法1:使用求和法 原数组的和为s0,第一组数组的和为s1,则第一个被去掉的数为 s0 - s1。 第二组数组的和为s2,则第二个被去掉的数为 s1 - s2。 方法2:使用排序或哈希表(统计频率) 原数组为a,第一组数组为b,第二组数组为c。 第一个被去掉的元素:在a中出现但不在b中出现的元素,或者在a中比b中多出现一次的元素。 第二个被去掉的元素:在b中出现但不在c中出现的元素,或者在b中比c中多出现一次的元素。 考虑到可能有重复元素,所以使用统计频率的方法更可靠。 具体步骤: 1. 读入原数组a(长度为n),第一组数组b(长度为n-1),第二组数组c(长度为n-2)。 2. 分别统计a、b、c中每个元素的出现频率。 3. 第一个答案:遍历a的元素,找到在a中出现的次数比在b中多一次的元素(或者遍历b的元素,但注意a中可能有b没有的元素,所以遍历a更安全)。 具体:对于a中的每个元素x,如果a中x的频率比b中x的频率大1,则x就是第一个被去掉的。 但注意:因为b中可能没有x,所以当b中不存在x时,b中x的频率为0,此时a中x的频率应该是1(比0大1),所以成立。 4. 第二个答案:同理,遍历b的元素,找到在b中出现的次数比在c中多一次的元素。 但是需要注意:同一个元素可能在数组中出现多次,所以不能只用一个标记,必须统计频率。 另一种方法:由于题目保证答案唯一,我们可以用以下方法: 第一个答案 = 在数组a中出现但在数组b中少出现一次的元素(即a中比b中多一个的元素)。 第二个答案 = 在数组b中出现但在数组c中少出现一次的元素。 实现: 使用map来统计每个数组的元素频率。 但是注意:在统计第二个答案时,我们要在b中找比c中多一次的元素,而b中已经包含第一个答案,所以第一个答案在b中可能比a中少一次,但我们并不关心,因为第二个答案与第一个答案不同。 步骤: 1. 读入n,然后读入三个数组。 2. 分别用三个map统计a, b, c中每个元素的频率。 3. 遍历a中的每个元素,对于每个元素x,如果freq_a[x] != freq_b[x](实际上应该大1),则第一个答案就是x,并跳出(但注意可能有多个?题目保证唯一,所以找到一个即可?但是因为同一个元素出现多次,我们只需找到一个元素在a中频率比b中多1即可,但这样的元素只有一个,因为只去掉一个元素,所以整个数组a中只有一个元素会多一次。但实际上,如果有重复元素,那么可能有多个元素在a中的频率比b中多1?但是仔细分析:只去掉一个元素,所以整个数组a和b之间,只有被去掉的那个元素在a中的频率比b中多1,其他元素都相同。所以我们可以遍历a,找到第一个满足freq_a[x] > freq_b[x]的元素,然后输出并跳出?但是有可能这个元素在b中不存在,所以用freq_b[x]可能为0。 具体:我们可以这样: for (auto x: a) { if (freq_a[x] - freq_b[x] == 1) { first = x; break; } } 但是注意:在遍历时,同一个x可能出现多次,所以不能一找到就break,因为可能后面还有?不对,因为同一个x,我们通过频率比较,如果这个x在a中出现了k次,那么在b中出现了k-1次,那么当我们遍历到x时,就会满足条件。但是这样会多次检测到同一个x,所以我们可以记录下这个x,然后跳出循环?但是这样会重复记录同一个x多次。因此,我们可以遍历map,而不是遍历数组a。 改进:遍历频率映射: for (auto it : freq_a) { int x = it.first; if (it.second - freq_b[x] == 1) { first = x; break; } } 但是这里要注意:freq_b中可能没有x,所以我们需要检查x是否在freq_b中?或者我们初始化freq_b时,对于a中所有元素都初始化了?没有。所以我们可以这样:使用map的find方法,或者直接访问freq_b[x],如果x不在freq_b中,则返回0(因为我们使用map,默认值0)。 同样,第二个答案:遍历freq_b,找freq_b[x] - freq_c[x] == 1的元素。 但是注意:第一个答案也可能在b中出现(在c中不出现)吗?第二个答案只与b和c有关,所以这样找没有问题。 但是:第一个答案被去掉后,在b中就不存在了?不对,b是去掉第一个答案后的数组,所以第一个答案在b中出现的次数应该比a中少1(如果a中出现了多次,那么b中只少一次)。所以我们的方法正确。 但是:如果a中有重复元素,比如a=[2,2,3],b=[2,3],那么第一个被去掉的是2。那么freq_a[2]=2,freq_b[2]=1,所以2满足条件。而其他元素(3)在a和b中频率相等。 所以我们可以使用频率差的方法。 步骤: 1. 读入n,然后读入数组a(n个数),数组b(n-1个数),数组c(n-2个数)。 2. 定义三个map:freq_a, freq_b, freq_c。 3. 统计a中每个元素的频率,b中每个元素的频率,c中每个元素的频率。 4. 遍历freq_a,找到第一个满足 freq_a[x] - (freq_b.count(x)?freq_b[x]:0) == 1 的x,作为第一个答案。 5. 遍历freq_b,找到第一个满足 freq_b[x] - (freq_c.count(x)?freq_c[x]:0) == 1 的x,作为第二个答案。 但是注意:第一个答案可能有多个元素满足条件吗?题目保证唯一,所以只有一个元素会被去掉,所以只有一个元素满足这个条件。因此,我们找到第一个满足条件的x即可(但map遍历是随机的,所以最好直接遍历,然后输出找到的第一个,因为只有一个)。 但是,我们也可以不用map遍历,而是遍历数组a(但数组a有重复,所以可能重复找到同一个元素多次)。所以还是遍历map比较好。 但是注意:题目要求按顺序输出:先输出的第一个被去掉的,再输出第二个被去掉的。 所以,我们也可以这样: 第一个答案:遍历a,直到找到一个元素x,使得freq_a[x] > freq_b[x](并且我们每找到一个,就在freq_b[x]上加1?这样不行)。所以还是用map统计后直接查找。 代码实现: 注意:由于n最大10^5,所以用map统计不会超时(O(n log n))。 另外:也可以使用unordered_map(平均O(n))。 代码: 方法1:使用map(或unordered_map)统计频率。 但是:题目要求按顺序输出两个答案,所以先输出第一个被去掉的,再输出第二个。 步骤: 1. 读入数组a,b,c。 2. 统计频率: map<int, int> fa, fb, fc; for (int i=0; i<n; i++) fa[a[i]]++; for (int i=0; i<n-1; i++) fb[b[i]]++; for (int i=0; i<n-2; i++) fc[c[i]]++; 3. 然后: int first = 0, second = 0; for (auto it : fa) { int num = it.first; if (it.second != fb[num]) { // 因为只少一个,所以一定是fa[num] == fb[num] + 1 first = num; break; // 因为只有一个,所以找到就可以退出 } } for (auto it : fb) { int num = it.first; if (it.second != fc[num]) { second = num; break; } } 4. 输出 first 和 second。 但是,注意:在第一个循环中,我们遍历fa,然后比较fa[num]和fb[num](如果num不在fb中,fb[num]默认0)。但是当fa[num]不等于fb[num]时,我们直接取num作为第一个答案并跳出。因为只少一个元素,所以这样的元素只有一个。 但是:在第二个循环中,同样遍历fb,然后比较fb[num]和fc[num](如果num不在fc中,则fc[num]为0)。 但是:有没有可能第一个循环中,有多个元素满足fa[num]!=fb[num]?题目保证答案唯一,所以只有一个元素被去掉,所以只有一个元素满足fa[num]!=fb[num](即fa[num]比fb[num]大1,而其他都相等)。 但是,我们这样写可能会遇到问题:如果一个元素在a中不存在,但在fa中不会出现(因为我们遍历fa,所以不会出现这种情况)。所以正确。 但是:如果第一个答案在a中只出现一次,那么fb中这个元素就不存在(即fb[num]为0),此时fa[num]=1,fb[num]=0,满足不等。 所以,这个方法正确。 但是,有一个小问题:遍历map时,我们不知道顺序,但题目不要求顺序,只要输出那个被去掉的元素即可(因为答案唯一),所以任意顺序遍历map都可以。 但是,我们也可以不用map,而用数组求和法(更简单,且O(n)): long long s1 = 0, s2 = 0, s3 = 0; for (int i=0; i<n; i++) s1 += a[i]; for (int i=0; i<n-1; i++) s2 += b[i]; for (int i=0; i<n-2; i++) s3 += c[i]; int first = s1 - s2; int second = s2 - s3; 求和法更简单,且效率高(O(n)),但要注意数据范围:n最大10^5,元素最大10^9,那么s1最大10^14,所以用long long不会溢出(long long最大9e18)。 所以,推荐使用求和法。 但是,求和法有一个问题:如果数组中有重复元素,并且被去掉的元素是重复的,会不会影响?不会,因为求和法就是计算总和,去掉一个元素,那么两个数组的差就是这个元素。 所以,求和法完全正确。 因此,我们可以写两种方法,但这里推荐求和法(更简单高效)。 代码(求和法): #include <iostream> using namespace std; int main() { int n; cin >> n; long long a_sum = 0, b_sum = 0, c_sum = 0; int x; for (int i = 0; i < n; i++) { cin >> x; a_sum += x; } for (int i = 0; i < n-1; i++) { cin >> x; b_sum += x; } for (int i = 0; i < n-2; i++) { cin >> x; c_sum += x; } long long first = a_sum - b_sum; long long second = b_sum - c_sum; cout << first << endl; cout << second << endl; return 0; } 但是,题目要求输出两个答案,第一个答案和第二个答案。 但是,有没有可能多个不同的元素被去掉,但是和相同?题目没有说元素互不相同,所以有可能出现两个不同的元素和相同吗?题目要求去掉两个元素(但这两个元素可能相同),但是注意:在第一个数组中,去掉一个元素后得到第二个数组,再去掉一个元素得到第三个数组。所以两个被去掉的元素可能是相同的。 但是,用求和法:第一个答案 = a_sum - b_sum,第二个答案 = b_sum - c_sum。 如果两个被去掉的元素相同,比如a_sum - b_sum = X,b_sum - c_sum = X,那么输出两个X。 所以,求和法完全正确。 但是,题目中是否有说明元素互不相同?没有,所以可能重复。 因此,我们使用求和法。 但是,注意:题目要求输入输出格式,以及多个测试用例?看题目描述:输入第一行是n,然后第二行是n个整数(原数组),第三行是n-1个整数(第一组),第四行是n-2个整数(第二组)。 所以,我们只需要读入一次。 但是,题目中可能有多个测试用例?不,题目描述:The first line contains integer n (3≤n≤10^5) — the initial length of the array. 所以只有一个测试用例。 但是,我们再看题目:Input中第一行是n,所以代码按单组输入。 所以,最终代码: 注意:使用long long,因为元素最大10^9,n最大10^5,总和最大10^14。 代码: </think> 对于 Codeforces 519B 问题,我将提供两种优化解法:**求和法**(推荐)和**频率统计法**。原始问题需要找出两次删除操作中被移除的元素。 ### 解法一:求和法(O(n) 时间复杂度) 这是最优解法,利用数组和的差值直接计算被移除的元素: ```cpp #include <iostream> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; long long a_sum = 0, b_sum = 0, c_sum = 0; int x; // 读取原始数组并求和 for (int i = 0; i < n; i++) { cin >> x; a_sum += x; } // 读取第一次删除后的数组并求和 for (int i = 0; i < n - 1; i++) { cin >> x; b_sum += x; } // 读取第二次删除后的数组并求和 for (int i = 0; i < n - 2; i++) { cin >> x; c_sum += x; } // 计算被移除的元素 long long first_removed = a_sum - b_sum; long long second_removed = b_sum - c_sum; cout << first_removed << "\n"; cout << second_removed << "\n"; return 0; } ``` #### 代码解释: 1. **输入处理**: - 读取数组大小 `n` - 使用 `long long` 防止总和溢出(元素值 ≤10⁹,n≤10⁵,总和最大 10¹⁴) 2. **求和计算**: - `a_sum`:原始数组总和 - `b_sum`:第一次删除后数组(n-1 个元素)总和 - `c_sum`:第二次删除后数组(n-2 个元素)总和 3. **差值计算**: - `first_removed = a_sum - b_sum`:第一个被删除的元素 - `second_removed = b_sum - c_sum`:第二个被删除的元素 4. **时间复杂度**:O(n),仅需三次线性遍历 ### 解法二:频率统计法(O(n log n) 时间复杂度) 使用哈希表统计元素频率,适合元素值范围大的情况: ```cpp #include <iostream> #include <vector> #include <unordered_map> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector<int> a(n), b(n-1), c(n-2); unordered_map<int, int> freq_a, freq_b, freq_c; // 读取并统计原始数组频率 for (int i = 0; i < n; i++) { cin >> a[i]; freq_a[a[i]]++; } // 读取并统计第一次删除后数组频率 for (int i = 0; i < n - 1; i++) { cin >> b[i]; freq_b[b[i]]++; } // 读取并统计第二次删除后数组频率 for (int i = 0; i < n - 2; i++) { cin >> c[i]; freq_c[c[i]]++; } // 查找第一个被删除的元素 int first_removed = 0; for (int num : a) { if (freq_a[num] != freq_b[num]) { first_removed = num; break; } } // 查找第二个被删除的元素 int second_removed = 0; for (int num : b) { if (freq_b[num] != freq_c[num]) { second_removed = num; break; } } cout << first_removed << "\n"; cout << second_removed << "\n"; return 0; } ``` #### 代码解释: 1. **数据结构**: - 使用 `unordered_map` 存储元素频率(平均 O(1) 操作) - `vector` 存储输入数组 2. **频率统计**: - `freq_a`:原始数组频率 - `freq_b`:第一次删除后频率 - `freq_c`:第二次删除后频率 3. **查找被删元素**: - 第一个元素:在 `a` 中频率比 `b` 大 1 的元素 - 第二个元素:在 `b` 中频率比 `c` 大 1 的元素 4. **时间复杂度**:O(n log n)(哈希表操作均摊 O(1)) ### 两种解法对比 | 特性 | 求和法 | 频率统计法 | |--------------|---------------------------|--------------------------| | 时间复杂度 | O(n) | O(n)(均摊) | | 空间复杂度 | O(1) | O(n) | | 适用场景 | 推荐通用解法 | 元素范围极大时更稳定 | | 优势 | 代码简洁,内存占用少 | 不依赖数值计算 | | 注意事项 | 总和可能溢出(用long long)| 哈希冲突可能影响性能 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值