POJ·Pipe

初見安~這裏是傳送門:POJ P1039 Pipe

Sol

計算幾何的一個入門題目呢。

有一個可能初學不太容易發現的點就是:要這條光線到最遠,那麼擦邊過的一定是最優解【並不是說最優解就只能是擦邊過的】,也就是一定過了至少一個上界和一個下界。那不就簡單了嘛,兩點確定一條直線,我們枚舉一個上界點和一個下界點確定一條直線,然後從1~n確認這條直線的合法性以及走到了哪個位置。思路比較好理解。

接下來就是關於實現了,也就是計算幾何的硬操作。首先我們要判斷這條直線依次經過各個管道的拐點是否有不合法,也就是這條直線在拐點的地方是否高於上界或者低於下界。有兩個方法,一個是直接求出直線的解析式看y座標的位置,還有一個【參考代碼所用的方法,好像更麻煩一些】就是利用叉積的正負。因爲如果這條直線沒有超出管道,那麼該直線順時針旋轉和逆時針旋轉可以分別碰到該拐點的上界和下界,即兩個叉積異號【至於是哪兩兩向量乘出來的兩個叉積就自己想吧】。

再來就是如果超出管道了,要求交點的x座標。這個……求兩個直線解析式然後一發帶走吧。

上代碼了。【其實計算幾何的話除了基本操作,別的地方的代碼都不建議看。寫法太多了

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define maxn 50
using namespace std;
typedef long long ll;
typedef long double ld;
const ld eps = 1e-8L;
int read() {
	int x = 0, f = 1, ch = getchar();
	while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
	while(isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar();
	return x * f;
}

int n;
struct node {ld x, y;} up[maxn], down[maxn];
int change(ld x) {if(x > eps) return 1; if(x < -eps) return -1; return 0;}//返回正負
ld fun(ld x1, ld y1, ld x2, ld y2) {return x1 * y2 - x2 * y1;}//返回叉積
ld cross(node a, node b, node c) {return fun(b.x - a.x, b.y - a.y, c.x - a.x, c.y - a.y);}//作差一下再扔叉積
ld get_x(node a, node b, node c, node d) {//求兩直線交點的x座標
	ld k1, k2, b1, b2;
	k1 = (b.y - a.y) / (b.x - a.x), k2 = (d.y - c.y) / (d.x - c.x);
	b1 = a.y - k1 * a.x, b2 = d.y - k2 * d.x;
	return (b2 - b1) / (k1 - k2);
}

bool check(int i, int j, int k) {return change(cross(up[i], down[j], up[k])) * change(cross(up[i], down[j], down[k])) > 0;}//判定是否超出管道
void solve() {
	ld ans = -1000000000.0;
	for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) if(i != j) {
		register int k = 1;
		for(k; k <= n; k++) if(check(i, j, k)) break;
		if(k > n) {puts("Through all the pipe."); return;}
		ld tmp = 0.0;
		if(k < max(i, j)) continue;
		tmp = max(get_x(up[i], down[j], up[k], up[k - 1]), get_x(up[i], down[j], down[k], down[k - 1]));
		ans = max(ans, tmp);
	}
	printf("%.2Lf\n", ans);
}
signed main() {
	while(n = read()) {
		if(!n) return 0;
		for(int i = 1; i <= n; i++) scanf("%Lf%Lf", &up[i].x, &up[i].y), down[i].x = up[i].x, down[i].y = up[i].y - 1.0;
		solve();
	}
	return 0;
}

迎評:)
——End——

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章