首页 > 代码库 > Balloon
Balloon
题目链接
- 题意:
给定n组球心,每一组有两个球体,每一组只能选择一个球。现在需要选n个球,求选择的所有球体的R的最大值且互相不重叠
这题有一个需要注意的点:题目要求最后round后答案仍满足,那么直接取后三位就是答案,直接printf后由于会四舍五入导致wrong - 分析:
每组有两种选择,且互斥,就是twosat的题目了,直接二分R加twosat即可。
将i组和j组的两个球分别标号为0和1,那么当两个球ii和jj不满足当前的R值时,说明i组和j组不能选择ii号球和jj号球,那么即 (i = ii ^ 1) OR (j = jj ^ 1),套用模板加边即可
const double EPS = 1e-9; const int MAXV = 100010; struct TwoSAT { int n; vector<int> G[MAXV*2]; bool mark[MAXV*2]; int S[MAXV*2], c; void init(int n) { this->n = n; for (int i = 0; i < n*2; i++) G[i].clear(); memset(mark, 0, sizeof(mark)); } bool dfs(int x) { if (mark[x^1]) return false; if (mark[x]) return true; mark[x] = true; S[c++] = x; for (int i = 0; i < G[x].size(); i++) if (!dfs(G[x][i])) return false; return true; } // x = xval or y = yval void add_clause(int x, int xval, int y, int yval) { x = x * 2 + xval; y = y * 2 + yval; G[x^1].push_back(y); G[y^1].push_back(x); } bool solve() { for(int i = 0; i < n*2; i += 2) if(!mark[i] && !mark[i+1]) { c = 0; if(!dfs(i)) { while(c > 0) mark[S[--c]] = false; if(!dfs(i+1)) return false; } } return true; } } tst; int n, m; struct Point { double x, y, z; inline void read() { scanf("%lf%lf%lf", &x, &y, &z); } } ipt[MAXN][2]; inline double dis(Point pa, Point pb) { return sqrt(sqr(pa.x - pb.x) + sqr(pa.y - pb.y) + sqr(pa.z - pb.z)); } bool check(double Min) { tst.init(n); REP(i, n) FF(j, i + 1, n) { REP(ii, 2) REP(jj, 2) { double d = dis(ipt[i][ii], ipt[j][jj]); if (d < Min) { tst.add_clause(i, ii ^ 1, j, jj ^ 1); } } } return tst.solve(); } int main() { while (~RI(n)) { REP(i, n) REP(j, 2) ipt[i][j].read(); double l = 0, r = 1e20, m; while (l + EPS < r) { m = (l + r) / 2; if (check(m * 2)) l = m; else r = m; } printf("%.3f\n", (int)(r * 1000) / 1000.0); } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。