【POJ】2165.Gunman

题解

把直线的斜率分解成二维,也就是随着z的增加x的增量和y的增量
我们发现一条合法直线向上移一点一定能碰到一条横线
知道了这条横线可以算出y的斜率
我们旋转一下,让这条横线碰到两条竖线,就可以算出x的斜率,进而判断直线在不在平面内

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
//#define ivorysi
#define MAXN 105
#define eps 1e-8
using namespace std;
typedef long long int64;
typedef double db;
struct plane{
    double x[2],y[2],z;
}pl[MAXN];
struct Point{
    double x,y;
}P[MAXN * 4];
int N,cnt;
db yk,xk,sx;
void Init() {
    scanf("%d",&N);
    for(int i = 1 ; i <= N ; ++i) {
	scanf("%lf%lf%lf%lf%lf",&pl[i].x[0],&pl[i].y[0],&pl[i].x[1],&pl[i].y[1],&pl[i].z);
    }
}
void Solve() {
    for(int i = 1 ; i <= N ; ++i) {
	for(int r = 0 ; r <= 1 ; ++r) {
	    db k = pl[i].y[r] / pl[i].z;
	    cnt = 0;
	    bool flag = 0;
	    for(int j = 1 ; j <= N ; ++j) {
		if(pl[j].z * k > pl[j].y[1] + eps || pl[j].z * k < pl[j].y[0] - eps) goto succ;
		for(int c = 0 ; c <= 1 ; ++c) {
		    P[++cnt] = (Point){pl[j].x[c],pl[j].z};
		}
	    }
	    yk = k;
	    for(int j = 1 ; j <= cnt ; ++j) {
		for(int h = j + 1 ; h <= cnt ; ++h) {
		    if(P[j].y == P[h].y) continue;
		    flag = 1;
		    k = (P[j].x - P[h].x) / (P[j].y - P[h].y);
		    
		    if(P[j].x == P[h].x) k = 0;
		    sx = P[j].x - P[j].y * k;
		    for(int l = 1 ; l <= N ; ++l) {
			db tmp = sx + k * pl[l].z;
			if(tmp < pl[l].x[0] - eps || tmp > pl[l].x[1] + eps) {flag = 0;break;}
		    }
		    if(flag) {
			xk = k;goto succ;
		    }
		} 
	    }
	    succ:;
	    if(flag) {
		puts("SOLUTION");
		printf("%.6f
",sx);
		for(int i = 1 ; i <= N ; ++i) {
		    printf("%.6f %.6f %.6f
",sx + xk * pl[i].z,yk * pl[i].z,pl[i].z);
		}
		return;
	    }
	}
    }
    puts("UNSOLVABLE");
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Init();
    Solve();
}

原文地址:https://www.cnblogs.com/ivorysi/p/9039170.html