原题链接:https://www.luogu.com.cn/problem/P2831
难度:提高+/省选-(TG D2T3)
涉及知识点:数学【抛物线(二次函数)】、状态压缩DP
题意
在一个平面直角坐标系上,点 ( 0 , 0 ) (0,0) (0,0) 处是一架弹弓,给定 n n n 个形如 ( x , y ) (x,y) (x,y) 的坐标,表示小猪的分布点,要求求出至少需要打出多少只小鸟才能把所有小猪消灭,小鸟的飞行轨迹是形 y = a x 2 + b x ( a < 0 ) y=ax^2+bx(a<0) y=ax2+bx(a<0) 的曲线(向下开口的抛物线)。以及给出了一些对正解没有实质帮助但有助于暴力求解时优化的 m m m 号指令。
分析与解决
一条抛物线可以打到若干只小猪,求至少需要多少条抛物线,这就是题目的核心。不难发现这是经典的重复覆盖问题,可以使用 D a n c i n g L i n k s Dancing \ Links Dancing Links 求解。但显然这不应该是NOIP提高组的考点,看一看数据范围, n ≤ 18 n\leq 18 n≤18,那就完全可以把小猪进行状态压缩,再 D P DP DP 求解。
考虑先预处理抛物线,通过两点确定一条抛物线的方法,也就是说至多会有 n 2 n^2 n2 条抛物线,每次先用两个点定一条抛物线,再枚举所有点,把所有位于该条抛物线上的小猪都记录下来,最后用 p a t h [ i ] [ j ] = s t a t e path[i][j]=state path[i][j]=state 表示以 第 i i i 和第 j j j 个点确定的一条抛物线打过的小猪状态是 s t a t e state state。需要注意三个问题:
- 枚举的两个点一定要判断 x 1 ≠ x 2 x_1\neq x_2 x1=x2,否则不符合两点定线原则。
- 两点确定的抛物线需要计算系数 a a a 和 b b b,以便于判断开口问题以及确定某个点是否在抛物线上。如果 a > 0 a>0 a>0,则开口朝上是不符合题意的,如果 a = 0 a=0 a=0 那就变成一次函数了(初中数学)。
- 判断大小时要注意一下精度问题,如果两个数的差在一个很小的精度范围内,我们就认为两数相等。
坐标的 x x x 和 y y y 值是直接读入的,那如何计算系数 a a a<