信息学奥赛一本通 1951:【10NOIP普及组】导弹拦截 | 洛谷 P1158 [NOIP 2010 普及组] 导弹拦截

【题目链接】

ybt 1951:【10NOIP普及组】导弹拦截
洛谷 P1158 NOIP 2010 普及组 导弹拦截

【题目考点】

1. 预处理+枚举

【解题思路】

第一个拦截系统的坐标为 P 1 P_1 P1,第二个拦截系统的坐标为 P 2 P_2 P2。

拦截系统可以拦截的范围是以拦截系统所在坐标为圆心的一个圆。

第一个拦截系统的拦截范围称为"第一个圆",第二个拦截系统的拦截范围称为"第二个圆。导弹所在位置为多个点。

题目所求为:使得两圆包含所有给定点的前提下,两圆半径的平方和最小。

思路上相当于不断扩大第一个圆半径,第一个圆包含了一些点,第二个圆就要包含剩下的点。
d i s ( i , j ) dis(i,j) dis(i,j)表示 i 、 j i、j i、j两点之间距离的平方。
a a a序列保存所有点,将 a a a序列按照到 P 1 P_1 P1的距离从小到大进行排序。
d p 1 i dp1_i dp1i表示第一个圆包含前 i i i个点时,半径的平方。

  • 初值: d p 1 0 = 0 dp1_0=0 dp10=0
  • 前 i i i个点中,距离 P 1 P_1 P1最远的点为 a i a_i ai,因此: d p 1 i = d i s ( a i , P 1 ) dp1_i=dis(a_i, P_1) dp1i=dis(ai,P1)。

d p 2 i dp2_i dp2i表示第二个圆包含第 i i i到第 n n n个点时,半径的平方。

  • 初值: d p 2 n + 1 = 0 dp2_{n+1}=0 dp2n+1=0
  • 第 i i i到第 n n n个点中距离 P 2 P_2 P2最远的点,可能是第 i + 1 i+1 i+1到第 n n n个点钟距离 P 2 P_2 P2最远的点,其距离的平方为 d p 2 i + 1 dp2_{i+1} dp2i+1;也可能是第 i i i个点,其距离的平方为 d i s ( a i , P 2 ) dis(a_i,P_2) dis(ai,P2),二者取较大值。因此: d p 2 i = m a x ( d p 2 i + 1 , d i s ( a i , P 2 ) ) dp2_i=max(dp2_{i+1}, dis(a_i, P_2)) dp2i=max(dp2i+1,dis(ai,P2))

枚举分割点 i i i,第1到第 i i i点被第一个圆包含,第 i + 1 i+1 i+1到第 n n n个点被第二个圆包含。 i i i最小为0,即第二个圆包含所有点。 i i i最大为 n n n,即第一个圆包含所有点。

当分割点为 i i i时,此时的代价为第一个圆的半径的平方 d p 1 i dp1_i dp1i与第二个圆半径的平方 d p 2 i + 1 dp2_{i+1} dp2i+1的加和: d p 1 i + d p 2 i + 1 dp1_i+dp2_{i+1} dp1i+dp2i+1,求所有出现的该值的最小值,即为本题的结果。

相同的思路,也可以变递推为迭代。

【题解代码】

解法1:预处理+枚举

  • 写法1:递推
cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
struct Pair
{
    int x, y;
} p1, p2, a[N]; 
int dp1[N], dp2[N];
int disSquare(Pair a, Pair b)//距离的平方 
{
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
bool cmp(Pair a, Pair b)
{
    return disSquare(a, p1) < disSquare(b, p1);
}
int main()
{
    int n, ans = 1e9;
    cin >> p1.x >> p1.y >> p2.x >> p2.y >> n;
    for(int i = 1; i <= n; ++i)
        cin >> a[i].x >> a[i].y;
    sort(a+1, a+1+n, cmp);
    for(int i = 1; i <= n; ++i)
    	dp1[i] = disSquare(a[i], p1);//dp1[i]:a[1]~a[i]各点到p1的最大距离 
    for(int i = n; i >= 1; --i)
    	dp2[i] = max(dp2[i+1], disSquare(a[i], p2));//dp2[i]:a[i]~a[n]各点到p2的最大距离
    for(int i = 0; i <= n; ++i)//0~i归系统1 i+1~n归系统2 
        ans = min(ans, dp1[i]+dp2[i+1]);
    cout << ans;
    return 0;
}
  • 写法2:迭代
cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
struct Pair
{
    int x, y;
} p1, p2, a[N]; 
int disSquare(Pair a, Pair b)//距离的平方 
{
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
bool cmp(Pair a, Pair b)
{
    return disSquare(a, p1) < disSquare(b, p1);
}
int main()
{
    int n, ans = 1e9, r1, r2 = 0;//r1, r2:系统半径的平方
    cin >> p1.x >> p1.y >> p2.x >> p2.y >> n;
    for(int i = 1; i <= n; ++i)
        cin >> a[i].x >> a[i].y;
    sort(a+1, a+1+n, cmp);
    for(int i = n; i >= 1; --i)//1~i归系统1 i+1~n归系统2 
    {
        r1 = disSquare(a[i], p1); 
        ans = min(ans, r1+r2);
        r2 = max(r2, disSquare(a[i], p2)); 
    }
    cout << min(ans, r2);//考虑全部由系统2拦截的情况 
    return 0;
}
相关推荐
乐迪信息28 分钟前
港口船舶逆行怎么管?AI防爆摄像机搭载智能检测算法
大数据·人工智能·深度学习·算法·计算机视觉
无名猿1 小时前
shared_ptr 完全指南:引用计数、控制块与开销
c++·性能优化·内存管理·标准库·现代c++
Sirens.1 小时前
Java并发锁详解:六类锁策略与 synchronized 底层原理
java·前端·算法
和裕2 小时前
全纸结构重型纸箱能否满足 1 吨以上设备出口熏蒸豁免要求?通关合规性全解析
大数据·运维·网络·人工智能·算法
tangguofeng2 小时前
不带头结点的链队操作集(不含InitFlag)(C语言版)
算法
xailorliu3 小时前
SLIC_超像素算法
c++·opencv·目标检测·机器学习·计算机视觉
苏打豆4 小时前
CRISP源码阅读——基于ROS2力矩反馈控制器与速度加速度零空间
c++·线性代数·算法·矩阵·机器人
蛋蛋的就会顺顺的4 小时前
hot100——矩阵
java·数据结构·算法·leetcode·力扣
老歌老听老掉牙4 小时前
麻花钻切屑形态演变的力学机制与临界条件分析
python·算法·钻头