1011. Cut Rectangles (35)解题报告

这篇博客详细介绍了PAT甲级试题1011. Cut Rectangles (35)的解题过程。解题者分析了三种可能的切割情况:两个直角三角形、一个直角三角形加一个直角梯形、一个直角三角形加一个五边形,并指出每种情况如何组合成完整的长方形。
摘要由CSDN通过智能技术生成

原题链接:

1011. Cut Rectangles (35)


解题思路:

长方形切割有三种情况,下面分情况讨论:

  1. 两个直角三角形。这两个三角形斜边相等,另外两边两两相等,而且四个锐角可以相应组成两个直角。
  2. 一个直角三角形,一个直角梯形。斜边相等,且可以组成长方形。
  3. 一个直角三角形和一个五边形。斜边相等,且可以组成长方形。
约束条件:
直角三角形、直角梯形、五边形的直角边与坐标轴成0、45、90、135或180度。


通过画面:



代码:
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;

struct point {
  double x, y;
  point(const double x = 0.0, const double y = 0.0) : x(x), y(y) {}
  point operator-(point p2)
  {
    return point(x - p2.x, y - p2.y);
  }
};

bool judge(vector<point>& shape1, vector<point>& shape2);
double length(point p1, point p2);
double angle(point p1, point p2, point p3);
int dcmp(double d1, double d2);
bool leftHand(point p1, point p2, point p3);
const double pi = acos(-1);
const double delta = 1e-5;
int main()
{
  int n = 0, k1 = 0, k2 = 0;
  assert(1 == scanf("%d", &n));
  for (int i = 0; i < n; i++) {
    assert(1 == scanf("%d", &k1));

    vector<point> shape1, shape2;
    for (int i = 0; i < k1; i++) {
      point tmp;
      assert(scanf("%lf %lf", &tmp.x, &tmp.y) == 2);
      shape1.push_back(tmp);
    }
    if (!leftHand(shape1[0], shape1[1], shape1[2])) {
      reverse(shape1.begin(), shape1.end());
    }
    assert(scanf("%d", &k2) == 1);
    for (int i = 0; i < k2; i++) {
      point tmp;
      assert(2 == scanf("%lf %lf", &tmp.x, &tmp.y));
      shape2.push_back(tmp);
    }
    if (!leftHand(shape2[0], shape2[1], shape2[2])) {
      reverse(shape2.begin(), shape2.end());
    }
    if (judge(shape1, shape2)) {
      puts("YES");
    }
    else {
      puts("NO");
    }
  }
  return 0;
}

bool judge(vector<point>& shape1, vector<point>& shape2)
{
  if (shape1.size() < 3 || shape2.size() < 3 || shape1.size() > 5 || shape2.size() > 5){
    return false;
  }
  else if (shape1.size() + shape2.size() > 8) {
    return false;
  }
  else {
    if (shape1.size() > shape2.size()) {
      swap(shape1, shape2);
    }
    vector<double> angle1, angle2, segment1, segment2;
    for (int i = 0; i < (int)shape1.size(); i++) {
      segment1.push_back(length(shape1[(i - 1 + shape1.size()) % shape1.size()], shape1[i]));
      angle1.push_back(angle(shape1[(i - 1 + shape1.size()) % shape1.size()], shape1[i], shape1[(i + 1) % shape1.size()]));
    }
    for (int i = 0; i < (int)shape2.size(); i++) {
      segment2.push_back(length(shape2[(i - 1 + shape2.size()) % shape2.size()], shape2[i]));
      angle2.push_back(angle(shape2[(i - 1 + shape2.size()) % shape2.size()], shape2[i], shape2[(i + 1) % shape2.size()]));
    }
    if (shape1.size() == 4 && shape2.size() == 4) {
      bool flag = true;
      for (int i = 0; i < 4 && flag; i++) {
        for (int j = 0; j < 4 && flag; j++) {
          if (dcmp(segment1[i], segment2[j]) == 0) {
            bool flag2 = true;
            if (!((dcmp(angle1[(i - 1 + 4) % 4] + angle2[j], pi) == 0 && dcmp(angle1[i] + angle2[(j - 1 + 4) % 4], pi) == 0) || 
              (dcmp(angle1[i] + angle2[j], pi) == 0 && dcmp(angle1[(i - 1 + 4) % 4] + angle2[(j - 1 + 4) % 4], pi) == 0))) {
              flag2 = false;
            }
            if (dcmp(angle1[(i + 1) % 4], pi / 2) || dcmp(angle2[(j + 1) % 4], pi / 2)) {
              flag2 = false;
            }
            if (dcmp(angle1[(i + 2) % 4], pi / 2) || dcmp(angle2[(j + 2) % 4], pi / 2)) {
              flag2 = false;
            }
            if (flag2) {
              double res1 = angle(shape1[(i + 1) % 4] - shape1[(i + 2) % 4], point(0, 0), point(0, 1));
              double res2 = angle(shape2[(j + 1) % 4] - shape2[(j + 2) % 4], point(0, 0), point(0, 1));
              if (!((dcmp(res1, pi / 2) == 0 || dcmp(res1, 0) == 0 || dcmp(res1, pi) == 0 || dcmp(res1, pi / 2 * 3) == 0)
                && (dcmp(res2, pi / 2) == 0 || dcmp(res2, 0) == 0 || dcmp(res2, pi) == 0 || dcmp(res2, pi / 2 * 3) == 0))) {
                flag2 = !flag2;
              }
            }
            flag = !flag2;

          }
        }
      }
      return !flag;
    } // if 4 4
    else if (shape1.size() == 3 && shape2.size() == 3) {
      bool flag = true;
      for (int i = 0; i < 3 && flag; i++) {
        for (int j = 0; j < 3 && flag; j++) {
          if (dcmp(segment1[i], segment2[j]) == 0) {
            bool flag2 = true;
            if (!((dcmp(segment1[(i + 1) % 3], segment2[(j - 1 + 3) % 3]) == 0 && dcmp(segment1[(i - 1 + 3) % 3], segment2[(j + 1) % 3]) == 0) ||
              (dcmp(segment1[(i - 1 + 3) % 3], segment2[(j - 1 + 3) % 3]) == 0 && dcmp(segment1[(i + 1) % 3], segment2[(j + 1) % 3]) == 0))) {
              flag2 = false;
            }
            if (dcmp(angle1[(i + 1) % 3], pi / 2) != 0) {
              flag2 = false;
            }
            if (flag2) {
              double res1 = angle(shape1[(i + 1) % 3] - shape1[(i + 2) % 3], point(0, 0), point(0, 1));
              double res2 = angle(shape2[(j + 1) % 3] - shape2[(j + 2) % 3], point(0, 0), point(0, 1));
              if (!((dcmp(res1, pi / 2) == 0 || dcmp(res1, 0) == 0 || dcmp(res1, pi) == 0 || dcmp(res1, pi / 2 * 3) == 0)
                && (dcmp(res2, pi / 2) == 0 || dcmp(res2, 0) == 0 || dcmp(res2, pi) == 0 || dcmp(res2, pi / 2 * 3) == 0))) {
                flag2 = !flag2;
              }
            }
            flag = !flag2;
          
          }
        }
      }
      return !flag;
    } // if 3 3
    else if (shape1.size() == 3 && shape2.size() == 4 || shape1.size() == 4 && shape2.size() == 3) {
      bool flag = true;
      for (int i = 0; i < 3 && flag; i++) {
        for (int j = 0; j < 4 && flag; j++) {
          if (dcmp(segment1[i], segment2[j]) == 0) {
            bool flag2 = true;
            if (!(dcmp(angle1[i] + angle2[(j - 1 + 4) % 4], pi / 2) == 0 && dcmp(angle1[(i - 1 + 3) % 3] + angle2[j], pi) == 0) && 
              !(dcmp(angle1[i] + angle2[(j - 1 + 4) % 4], pi ) == 0 && dcmp(angle1[(i - 1 + 3) %3] + angle2[j], pi / 2) == 0)) {
              flag2 = false;
            }
            if (dcmp(angle1[(i + 1) % 3], pi / 2) != 0 || dcmp(angle2[(j + 1) % 4], pi / 2) != 0 || dcmp(angle2[(j + 2) % 4], pi / 2) != 0) {
              flag2 = false;
            }
            if (flag2) {
              double res1 = angle(shape1[(i + 1) % 3] - shape1[(i + 2) % 3], point(0, 0), point(0, 1));
              double res2 = angle(shape2[(j + 1) % 4] - shape2[(j + 2) % 4], point(0, 0), point(0, 1));
              if (!((dcmp(res1, pi / 2) == 0 || dcmp(res1, 0) == 0 || dcmp(res1, pi) == 0 || dcmp(res1, pi / 2 * 3) == 0)
                && (dcmp(res2, pi / 2) == 0 || dcmp(res2, 0) == 0 || dcmp(res2, pi) == 0 || dcmp(res2, pi / 2 * 3) == 0))) {
                flag2 = !flag2;
              }
            }
            flag = !flag2;
          }
        }
      } // outer for
      return !flag;
    } // if 3 4
    else {
      bool flag = true;
      for (int i = 0; i < 3 && flag; i++) {
        for (int j = 0; j < 5 && flag; j++) {
          if (dcmp(segment1[i], segment2[j]) == 0) {
            bool flag2 = true;
            if (!((dcmp(angle1[i] + angle2[(j - 1 + 5) % 5], pi) == 0 && dcmp(angle1[(i - 1 + 3) % 3] + angle2[j], pi) == 0) || 
              (dcmp(angle1[i] + angle2[j], pi) == 0 && dcmp(angle1[(i - 1 + 3) % 3] + angle2[(j - 1 + 5) % 5], pi) == 0))) {
              flag2 = false;
            }
            if (dcmp(angle1[(i + 1) % 3], pi / 2) != 0 || dcmp(angle2[(j + 1) % 5], pi / 2) != 0 || dcmp(angle2[(j + 2) % 5], pi / 2) != 0) {
              flag2 = false;
            }
            if (flag2) {
              double res1 = angle(shape1[(i + 1) % 3] - shape1[(i + 2) % 3], point(0, 0), point(0, 1));
              double res2 = angle(shape2[(j + 1) % 5] - shape2[(j + 2) % 5], point(0, 0), point(0, 1));
              if (!((dcmp(res1, pi / 2) == 0 || dcmp(res1, 0) == 0 || dcmp(res1, pi) == 0 || dcmp(res1, pi / 2 * 3) == 0)
                && (dcmp(res2, pi / 2) == 0 || dcmp(res2, 0) == 0 || dcmp(res2, pi) == 0 || dcmp(res2, pi / 2 * 3) == 0))) {
                flag2 = !flag2;
              }
            }
            flag = !flag2;
          }
        }
      }
      return !flag;
    }// if 3 5
  }
}

double length(point p1, point p2)
{
  double x = p1.x - p2.x;
  double y = p1.y - p2.y;
  return sqrt(x * x + y * y);
}
double angle(point p1, point p2, point p3)
{
  point v1 = p1 - p2;
  point v2 = p3 - p2;
  return acos((v1.x * v2.x + v1.y * v2.y) / (length(p1, p2) * length(p2, p3)));
}
int dcmp(double d1, double d2)
{
  if (fabs(d1 - d2) < delta) {
    return 0;
  }
  else if (d1 > d2) {
    return 1;
  }
  else {
    return -1;
  }
}
bool leftHand(point p1, point p2, point p3)
{
  return p1.x * p2.y - p1.y * p2.x + p2.x * p3.y - p2.y * p3.x + p3.x * p1.y - p3.y * p1.x > 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值