zoukankan      html  css  js  c++  java
  • Codeforces 849B Tell Your World (计算几何)

    题目链接 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;
    }
    
  • 相关阅读:
    mysql逻辑备份
    Configuring ProxySQL
    CSS伸缩布局
    溢出文字隐藏三种方式
    CSS过渡效果transition和动画
    伪元素before和after本质
    css滑动门技术
    字体图标iconfont
    CSS精灵技术(sprite)
    行内块和文字垂直对齐vertical-agign
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/7498986.html
Copyright © 2011-2022 走看看