Codeforces 849B Tell Your World (計算幾何)
阿新 • • 發佈:2017-09-09
continue int ++i 滿足 light size sizeof tar tell
題目鏈接 Tell Your World
題意 給出N個點(i, xi),問是否存在兩條平行的直線,使得每一個點恰好在兩條直線的其中一條上。
每條直線必須穿過至少一個點。
考慮每個點和第1個點的斜率,相同的用並查集弄成一個連通塊。
然後我們枚舉每個連通塊,判斷不在連通塊內的這些點是否在同一條直線上,且斜率必須滿足和另一條相等。
註意特殊情況
1號點單獨占一條直線,其他的點占另一條直線。
這種情況樣例裏就有。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) typedef long long LL; const int N = 1e3 + 10; const double eps = 1e-8; LL a[N]; int father[N], b[N], c[N], f[N]; int n, cnt = 0, ans = 0; double cc[N]; vector <int> v[N]; int getfather(int x){ return father[x] ? father[x] = getfather(father[x]) : x;} int main(){ scanf("%d", &n); rep(i, 1, n) scanf("%lld", a + i); rep(i, 2, n - 1){ rep(j, i + 1, n){ if ((LL)(i - 1) * (a[j] - a[1]) == (LL)(j - 1) * (a[i] - a[1])){ int fa = getfather(i), fb = getfather(j); if (fa ^ fb){ father[fa] = fb; } } } } rep(i, 2, n){ int x = getfather(i); if (!c[x]){ c[x] = ++cnt; v[cnt].push_back(i); } else v[c[x]].push_back(i); } ans = 0; rep(i, 1, cnt){ if ((int)v[i].size() == n - 1) continue; memset(b, 0, sizeof b); double AA = (double)(a[v[i][0]] - a[1]) / (v[i][0] - 1); for (auto u : v[i]) b[u] = 1; int now = 0; rep(j, 2, n) if (!b[j]) f[++now] = j; if (now == 1){ ans = 1; break; } int ff = 0; rep(j, 2, now) cc[++ff] = (double)(a[f[j]] - a[f[1]]) / (double)(f[j] - f[1]); sort(cc + 1, cc + ff + 1); bool fl = true; rep(j, 1, ff - 1) if (fabs(cc[j + 1] - cc[j]) > eps){ fl = false; continue; } if (!fl) continue; if (fabs(AA - cc[1]) < eps){ ans = 1; break; } } int ff = 0; rep(j, 3, n) cc[++ff] = (double)(a[j] - a[2]) / (double)(j - 2); sort(cc + 1, cc + ff + 1); bool fl = true; rep(j, 1, ff - 1) if (fabs(cc[j + 1] - cc[j]) > eps){ fl = false; break; } if (fl){ double AA = (double)(a[2] - a[1]); if (fabs(AA - cc[1]) > eps) ans = 1; } puts(ans ? "Yes" : "No"); return 0; }
Codeforces 849B Tell Your World (計算幾何)