1 条题解
-
0
20 分做法
20 分留给暴力。可以枚举所有两个点对 和 ,把从 点到 点的咒语 记下来。这样一共有 个咒语。
之后枚举子集,判断这 个咒语中最少选出哪些可以满足条件即可。
因此,时间复杂度为
100 分做法
以样例2为例。为了在每对米奇妙妙屋之间旅行,需要,,,但后两个移动实际上是不必要的,因为可以通过多次重复来实现。
设 为从米奇妙妙屋 到米奇妙妙屋 旅行时坐标的变化量。此外,假设 和 都能被 整除。那么,与其记住咒语,不如记住。
因此,一旦我们知道了坐标的变化量,我们可以将它们除以相同的数字,直到和不再有大于或等于的公共因子为止,以确定要记住的咒语。实际上,
可以通过将和除以它们的最大公约数(GCD)来找到这个咒语。
通过以上观察,我们可以证明对于每一对不同的米奇妙妙屋执行以下操作是最优的。
考虑从到的旅行。
首先,令,。然后,令,并将其转化为,。最后,记住咒语。
的时间复杂度为。因此,问题的总时间复杂度为。
#include <bits/stdc++.h> #define ll long long using namespace std; typedef pair < int, int > PII; const int SIZE = 5e2 + 5; int n; map < PII, int > vis; struct node { int x, y; } a[SIZE]; int main() { //freopen("mantra.in", "r", stdin); //freopen("mantra.out", "w", stdout); cin >> n; for (int i = 1; i <= n; ++ i) cin >> a[i].x >> a[i].y; int ans = 0; for (int i = 1; i <= n; ++ i) { for (int j = 1; j <= n; ++ j) { if (i == j) continue; int x = a[i].x - a[j].x, y = a[i].y - a[j].y; int d = __gcd(x,y); d = abs(d); x /= d, y /= d; if (!vis[(PII) {x, y}]) vis[(PII) {x, y}] = 1, ++ ans; //cout << x << " " << y << endl; } } printf("%lld\n", ans); return 0; }
- 1
信息
- ID
- 176
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 3
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者