Luogu_P2831
算法
- 搜索
思路
由于 \(n \le 18\),可以考虑搜索。
定义 \(dfs(cur, a, b)\) 表示搜索到了第 \(cur\) 头猪,使用了 \(a\) 条抛物线,前面还有 \(b\) 头猪为被击中。
对于一条抛物线 \(y=ax^{2}+bx+c\),需要三个点确定其解析式。由于题目钦定了抛物线必定经过 \((0,0)\),所以还需要两个点。在前面为被击中的 \(b\) 头猪中选择一头与第 \(cur\) 头猪配对。假设两头猪的坐标为 \((x_{1}, y_{1}), (x_{2},y_{2})\)。则
\[\begin{cases}
a x_{1}^{2} + b x_{1} = y_{1} \\
a x_{2}^{2} + b x_{2} = y_{2} \\
\end{cases}
\to
\begin{cases}
a = \frac{(y_{1} x_{2} - y_{2} x_{1})}{x_{1}^{2} x_{2} - x_{1} x_{2}^{2}} \\
b = \frac{y_{1} - x_{1}^{2} a}{x_{1}} \\
\end{cases}
\]
于是就可以得到这两头猪配对的抛物线解析式。
然后进行剪枝。如果由于前面未配对的猪必须要有一条单独的抛物线经过,所以有最优性剪枝: \(a + b > answer\) 时 return。
代码
#include <bits/stdc++.h>
using namespace std;
constexpr int N = 25;
constexpr double EPS = 1e-9;
pair<double, double> pig[N], line[N], unused[N];
int test_case, n, m, answer;
bool equal(double a, double b) {
return fabs(a - b) < EPS;
}
void dfs(int cur, int a, int b) {
if (a + b >= answer) {
return void();
} else if (cur > n) {
answer = min(answer, a + b);
return void();
}
double x = pig[cur].first, y = pig[cur].second;
bool crossed = false;
for (int i = 1; i <= a; i++) {
if (equal(line[i].first * x * x + line[i].second * x, y) == true) {
crossed = true;
break;
}
}
if (crossed == true) {
dfs(cur + 1, a, b);
} else {
for (int i = 1; i <= b; i++) {
double tx = unused[i].first, ty = unused[i].second;
if (equal(x, tx) == true) {
continue;
}
double pa = (y * tx - ty * x) / (x * x * tx - tx * tx * x);
double pb = (y - x * x * pa) / x;
if (pa >= 0) {
continue;
}
line[a + 1] = make_pair(pa, pb);
pair<double, double> tmp = unused[i];
for (int j = i; j <= b - 1; j++) {
unused[j] = unused[j + 1];
}
dfs(cur + 1, a + 1, b - 1);
for (int j = b; j > i; j--) {
unused[j] = unused[j - 1];
}
unused[i] = tmp;
}
unused[b + 1] = pig[cur];
dfs(cur + 1, a, b + 1);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin >> test_case;
while (test_case --) {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> pig[i].first >> pig[i].second;
}
answer = 100000;
dfs(1, 0, 0);
cout << answer << "\n";
}
return 0;
}
本文来自博客园,作者:Fallen_Leaf,转载请注明原文链接:https://www.cnblogs.com/FallenLeaf/p/18974632