zoukankan      html  css  js  c++  java
  • P1663 山

    写在前面

    简单的二分答案,稍微加点数学计算,很有意思。

    算法思路

    二分答案可行的原因:答案具有单调性。

    这道题目中证明一下:首先无限高显然是能看到任何一个点的,且山的每一条边都是对答案的一个限制,因此位置越低可能受到的限制就越多,能看到所有位置的机会就越少,直至出现不可行的答案。

    因此只需要统计出每一对相邻的折点,求解出这两点所在的直线方程。随后二分答案。

    对于每个可能二分到的答案,每条直线的限制都会与其构成一个一元不等式,将所有的不等式组成不等式组,判断其是否有解。

    Code

    #include<bits/stdc++.h>
    #define LF double
    
    const int Maxn = 5e3 + 5;
    const LF eps = 1e-2;
    
    int n, x5, y5, x6, y6;
    
    double k[Maxn], b[Maxn];
    
    int cnt = 0;
    void solve(int x3, int y3, int x4, int y4) {
    	cnt++;
    	k[cnt] = 1.000 * (y3 - y4) / (x3 - x4);
    	b[cnt] = 1.000 * y3 - 1.000 * k[cnt] * x3;
    }
    
    using namespace std;
    
    inline int read() {
    	int f = 1, w = 0; char ch = getchar();
    	for(; !isdigit(ch); ch = getchar()) if(ch == '- ') f = -1;
    	for(; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
    	return f * w;
    }
    
    bool check(LF h) {
    	LF lf = 0, rt = (LF)x6;
    	for(register int i = 1; i <= cnt; ++i) {
    		if(k[i] > 0) rt = min(rt, (h - b[i]) / k[i]);
    		else lf = max(lf, (h - b[i]) / k[i]);
    	}
    	return lf <= rt;
    }
    
    int main() {
    	n = read();
    	x5 = read(); y5 = read();
    	for(register int i = 1; i < n; ++i) {
    		x6 = read(); y6 = read();
    		solve(x5, y5, x6, y6);
    		x5 = x6; y5 = y6;
    	}
    	LF l = 0, r = 1000000, mid, ans;
    	while((l <= r) && (r - l > eps)) {
    		mid = (l + r) / 2;
    		if(check(mid)) {
    			ans = mid;
    			r = mid - eps;
    		}
    		else {
    			l = mid + eps;
    		}
    	}
    	printf("%.2lf", ans);
    	return 0;
    }
    
  • 相关阅读:
    MySQL命令2
    MySQL命令1
    前端之HTML1
    linux命令之df dh
    python call java jar
    redis-py中的坑
    YARN应用程序的开发步骤
    Yarn的服务库和事件库使用方法
    SSH无密码验证
    在centos 6.5 在virtual box 上 安装增强版工具
  • 原文地址:https://www.cnblogs.com/zimujun/p/13872486.html
Copyright © 2011-2022 走看看