zoj 2102 Tables

这题有2种情况可以满足棍子不掉落
1、重心在某个圆内部
2、重心两侧的棍身都分别有支撑圆

只需通过遍历圆然后判断即可

#include<iostream>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
#define eps 0.01
#define pi 3.1415926
using namespace std;

struct circle {
	double x, y, r;
	void sc() {
		scanf("%lf%lf%lf", &x, &y, &r);
	}
} cir[10000];

double getdis(double x1, double y1, double x2, double y2) {
	return sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}

double getcos(double a, double b, double c) {
	return (b * b + c * c - a * a) / (2.0 * b * c);
}

double crossed(double x1, double y1, double x2, double y2) {
	return x1 * y2 - y1 * x2;
}

int main() {
	int n, i, dir1, dir2, flag;
	double x1, y1, x2, y2, len, gx, gy, a, b, c, C, A, x, y, r, area, h;
	while (scanf("%d", &n) && n) {
		for (i = 0; i < n; i++) {
			cir[i].sc();
		}

		scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);

		dir1 = 0;
		dir2 = 0;
		flag = 0;
		len = getdis(x1, y1, x2, y2);
		gx = (x1 + x2) / 2.0;
		gy = (y1 + y2) / 2.0;

		for (i = 0; i < n; i++) {
			x = cir[i].x;
			y = cir[i].y;
			r = cir[i].r;

			//1、重心上有支撑桌
			//重心在圆内部
			if (getdis(x, y, gx, gy) < r) {
				flag = 1;
				break;
			}


			//2、两侧都有支持桌:

			//线段一端在圆内部
			if (getdis(x1, y1, x, y) < r) {
				dir1++;
				if (dir2) {
					flag = 1;
					break;
				}
				continue;
			}
			if (getdis(x2, y2, x, y) < r) {
				dir2++;
				if (dir1) {
					flag = 1;
					break;
				}
				continue;
			}

			//线段两端在圆外部
			a = getdis(x1, y1, x, y);
			b = len;
			c = getdis(x2, y2, x, y);

			C = acos(getcos(c, a, b));
			A = acos(getcos(a, b, c));

			if (C < acos(0) && A < acos(0)) {
				area = fabs(crossed(x - x1, y - y1, x2 - x1, y2 - y1));
				h = area / len;

				if (h < r) {
					if (a < c) {
						dir1++;
						if (dir2) {
							flag = 1;
							break;
						}
						continue;
					} else {
						dir2++;
						if (dir1) {
							flag = 1;
							break;
						}
						continue;
					}
				}
			}
		}

		if (flag) {
			printf("STAY\n");
		} else {
			printf("FALL\n");
		}

	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值