poj 3304

来源:互联网 发布:js vr 插件 互动 编辑:程序博客网 时间:2024/05/29 13:08

题目概述

给定N条线段端点坐标,问是否存在一直线,使所有线段在该直线上的投影有公共点

时限

1000ms/3000ms

输入

第一行正整数times,其后times组数据,每组数据第一行正整数N,其后N行,每行4个浮点数,每2个表示1个端点坐标

限制

1<=N<=100;浮点相对误差限EPS=1e-8

输出

每行一个字符串,若存在,为Yes!,否则为No!

样例输入

3
2
1.0 2.0 3.0 4.0
4.0 5.0 6.0 7.0
3
0.0 0.0 0.0 1.0
0.0 1.0 0.0 2.0
1.0 1.0 2.0 1.0
3
0.0 0.0 0.0 1.0
0.0 2.0 0.0 3.0
1.0 1.0 2.0 1.0

样例输出

Yes!
Yes!
No!

讨论

计算几何,题目直接做很麻烦,需要转化,首先要明确两点,其一,若存在题目要求的直线,则必然存在一条与之垂直的直线和所有线段相交,其二,若存在一条与所有直线相交的直线,则必然可通过旋转平移使其经过至少2个线段的端点(可能是同一条线段的),那么反过来利用这两条结论,只要枚举所有不重合的线段端点,构造直线,如果和所有线段相交,那就是存在了
今天刚开始接手计算几何,对一些细节不是很熟练,algorithm中包含math.h,但math.h中的abs是针对整数的,而cmath重载之后也可应用于浮点数,由于编译器太人性化,没有报错,足足贡献3个WA才发现这事

题解状态

180K,16MS,C++,1229B

题解代码

#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>//重载的abs在这里using namespace std;#define INF 0x3f3f3f3f  #define MAXN 103#define memset0(a) memset(a,0,sizeof(a))#define EPS 1e-8double x[MAXN * 2], y[MAXN * 2];//分别存放横纵坐标 一条线段2个点 所以需要双倍空间inline double xp(double x1, double y1, double x2, double y2, double x3, double y3)//cross_product 向量积 以点2为公共起点{    return (x1 - x2)*(y3 - y2) - (y1 - y2)*(x3 - x2);}inline bool intersect(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)//相交 由于是直线和线段关系 因而只要线段端点在直线两侧或有一个在直线上就算相交 默认前两点为直线的{    return xp(x3, y3, x1, y1, x2, y2)*xp(x4, y4, x1, y1, x2, y2) <= EPS;}void fun(int N){    for (int p = 0; p < N; p++)        scanf("%lf%lf%lf%lf", &x[p], &y[p], &x[N + p], &y[N + p]);//input    for (int p = 0; p < 2 * N; p++)        for (int i = p + 1; i < 2 * N; i++) {//枚举所有端点 找出2个做直线            if (abs(x[p] - x[i]) < EPS&&abs(y[p] - y[i]) < EPS)                continue;//重合的点就算了            bool no = 0;//是否存在直线与线段不相交的情况 初值不存在            for (int u = 0; u < N; u++) {                if (!intersect(x[p], y[p], x[i], y[i], x[u], y[u], x[u + N], y[u + N])) {                    no = 1;                    break;//有不相交的就要中断 继续枚举端点                }            }            if (!no) {//全部相交 存在                printf("Yes!\n");//output                return;            }        }    printf("No!\n");//output//都有不相交的情况 不存在}int main(void){    //freopen("vs_cin.txt", "r", stdin);    //freopen("vs_cout.txt", "w", stdout);    int times;    scanf("%d", &times);//input    while (times--) {        int N;        scanf("%d", &N);//input        fun(N);    }}

EOF

0 0
原创粉丝点击