POJ 1127 Jack Straws [计算几何]

2016年9月15日01:09:24更新
使用模板第二

#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstring>
using namespace std;
//Template
struct P {
  double x, y;
  P(double x = 0, double y = 0) : x(x), y(y) {}
  void read() {
    scanf("%lf%lf", &x, &y);
  }
  void print() {
    printf("%.6f %.6f", x, y);
  }
};
typedef P V;
V operator + (V a, V b) {
  return V(a.x+b.x, a.y+b.y);
}
V operator - (P a, P b) {
  return V(a.x-b.x, a.y-b.y);
}
V operator * (V a, double p) {
  return V(a.x*p, a.y*p);
}
V operator / (V a, double p) {
  return V(a.x/p, a.y/p);
}
const double eps = 1e-10;
int dcmp(double x) {
  if (abs(x) < eps) return 0;
  else return x < 0 ? -1 : 1;
}
bool operator == (P a, P b) {
  return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;
}
double operator * (V a, V b) {
  return a.x*b.x + a.y*b.y;
}
double norm(V a) {
  return sqrt(a*a);
}
double det(V a, V b) {
  return a.x*b.y - a.y*b.x;
}
double angle(V a, V b) {
  return acos(a*b / norm(a) / norm(b));
}
V rotate(V a, double rad) {
  return V(a.x*cos(rad) - a.y*sin(rad), a.x*sin(rad)+a.y*cos(rad));
}
//
P getLineIntersection(P p, V v, P q, V w) {
  V u = p - q;
  double t = det(w, u) / det(v, w);
  return p + v*t;
}
double ccw(P a, P b, P c)
{
   return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
}
bool isParallel(P a1, P a2, P b1, P b2) {
  return dcmp(det(a1 - a2, b1 - b2)) == 0;
}
bool intersects(P a1, P a2, P b1, P b2)
{
   if (ccw(a1, a2, b1) * ccw(a1, a2, b2) > 0) return false;
   if (ccw(b1, b2, a1) * ccw(b1, b2, a2) > 0) return false;
   return true;
}
bool onSeg(P q, P p1, P p2) {
  return dcmp(det(p1 - q, p2 - q)) == 0 && (p1 - q)*(p2 - q) <= 0;
}
bool isIntersect(P p1,P p2,P q1,P q2)
{
    if(max(p1.x,p2.x)<min(q1.x,q2.x)||max(q1.x,q2.x)<min(p1.x,p2.x)||max(p1.y,p2.y)<min(q1.y,q2.y)||max(q1.y,q2.y)<min(p1.y,p2.y))
        return 0;
    if(ccw(q1,q2,p1)*ccw(q1,q2,p2)<=0&&ccw(p1,p2,q1)*ccw(p1,p2,q2)<=0)
        return 1;
    else
        return 0;
}
//MAIN
const int MAXN = 13;
int n;
P p[MAXN], q[MAXN];
bool g[MAXN][MAXN];
void solve()
{
  for (int i = 0; i < n; i++) {
    p[i].read();
    q[i].read();
  }
  memset(g, 0, sizeof(g));
  for (int i = 0; i < n; i++) {
    g[i][i] = true;
    for (int j = 0; j < i; j++) {
     if (isIntersect(p[i], q[i], p[j], q[j])) {
        g[i][j] = true;
        g[j][i] = true;
      }
    }
  }
  for (int k = 0; k < n; k++) {
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        g[i][j] |= (g[i][k] && g[k][j]);
      }
    }
  }
  for (int i = 0; ; i++) {
    int a, b;
    scanf("%d%d", &a, &b);
    if (a == 0 && b == 0) break;
    puts(g[a-1][b-1] ? "CONNECTED" : "NOT CONNECTED");
  }
}
int main() {
  //freopen("in.txt", "r", stdin);
  for (;;) {
    scanf("%d", &n);
    if (n == 0) break;
    solve();
  }
}

Description

给n个线段,再个m个查询,问两个线段是否相连

reference

《挑战程序设计竞赛(第二版)》

Code

#include <cstdio> 
#include <cmath>
#include <iostream>
using namespace std;

const int maxn = 13;
const int maxm = 200;
const double eps = 1e-10;

int n;
//考虑误差的加法
double add(const double &a, const double &b)
{
  if (abs(a + b) < eps * (abs(a) + abs(b))) return 0;
  return a + b;
}

struct P
{
  double x, y;
  //两个构造函数 必须都写
  P() {}
  P(double x, double y) : x(x), y(y) {}
  //向量加法
  P operator + (P p)
  {
    return P(add(x, p.x), add(y, p.y));
  }
  //向量减法
  P operator - (P p)
  {
    return P(add(x, -p.x), add(y, -p.y));
  }
  //向量数乘
  P operator * (double d)
  {
    return P(x * d, y * d);
  }
  //向量 dot x1*x2+y1*y2
  double dot(P p)
  {
    return add(x * p.x, y * p.y);
  }
  //向量 det x1y2-x2y1
  double det(P p)
  {
    return add(x * p.y, -y * p.x);
  }
};
//判断点p是否在 线段p1-p2上
bool on_seg(P p1, P p2, P q)
{
  return (p1 - q).det(p2 - q) == 0 && (p1 - q).dot(p2 - q) <= 0;
}
//求交点
P intersection(P p1, P p2, P q1, P q2)
{
  return p1 + (p2 - p1) * ((q2 - q1).det(q1 - p1) / (q2 - q1).det(p2 - p1));
}

void solve()
{
  P p[maxn], q[maxn];
  for (int i = 0; i < n; i++)
  {
    int x1, y1, x2, y2;
    scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
    p[i].x = x1;
    p[i].y = y1;
    q[i].x = x2;
    q[i].y = y2;
  }
  bool g[maxn][maxn] = {false};
  for (int i = 0; i < n; i++)
  {
    g[i][i] = true;
    for (int j = 0; j < i; j++)
    //如果平行
      if ((p[i] - q[i]).det(p[j] - q[j]) == 0)
        g[i][j] = g[j][i] = on_seg(p[i], q[i], p[j])
                        || on_seg(p[i], q[i], q[j])
                        || on_seg(p[j], q[j], p[i])
                        || on_seg(p[j], q[j], q[i]);
      else
      {
        //求交点
        P r = intersection(p[i], q[i], p[j], q[j]);
        g[i][j] = g[j][i] = on_seg(p[i], q[i], r) && on_seg(p[j], q[j], r);
      }
  }
  //判断是否相连
  for (int k = 0; k < n; k++)
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++)
        g[i][j] |= g[i][k] && g[k][j];
  for (int i = 0; ; i++)
  {
    int a, b;
    scanf("%d%d", &a, &b);
    if (a == 0 && b == 0) break;
    puts(g[a-1][b-1] ? "CONNECTED" : "NOT CONNECTED");
  }
}

int main()
{
  for(;;)
  {
    scanf("%d", &n);
    if (n == 0) break;
    solve();
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值