熱門文章

2026年4月9日 星期四

ZeroJudge 解題筆記:d094. 00478 - Points in Figures: Rectangles and Circles, and Triangles

作者:王一哲
日期:2026年4月9日


ZeroJudge 題目連結:d094. 00478 - Points in Figures: Rectangles and Circles, and Triangles

解題想法


這題是 d093. 00477 - Points in Figures: Rectangles and Circles 的加強版,除了長方形、圓形之外還多了三角形,可以用上一題的程式碼為基礎,再加上檢查點是否在三角形內的自訂函式。 假設平面上的三角形 ABC 頂點座標分別為 $(x_A, y_A), (x_B, y_B), (x_C, y_C)$,如果要判斷平面上的點 P $(x_P, y_P)$ 是否在三角形之中,P 點座標可以表示為 $$ P = uA + vB + wC $$ 解聯立後可得 $$ \begin{align*} u &= \frac{(x_B - x_A)(y_P - y_A) - (y_B - y_A)(x_P - x_A)}{(x_B - x_A)(y_C - y_A) - (y_B - y_A)(x_C - x_A)}\\ v &= \frac{(x_C - x_A)(y_P - y_A) - (y_C - y_A)(x_P - x_A)}{(x_C - x_A)(y_B - y_A) - (y_C - y_A)(x_B - x_A)} \\ w &= 1 - u - v & \end{align*} $$ 係數符合的條件為
  • $0 \leq u \leq 1$
  • $0 \leq v \leq 1$
  • $0 \leq w \leq 1$


Python 程式碼


使用時間約為 9 ms,記憶體約為 8.6 MB,通過測試。
import sys

def in_rectangle(x, y, x1, y1, x2, y2):
    """
    代入要測試的點座標 (x, y)
    長方形左上頂點座標 (x1, y1)
    長方形右下頂點座標 (x2, y2)
    判斷點是否在長方形內
    """
    if x1 < x < x2 and y1 > y > y2: return True
    return False

def in_circle(x, y, xc, yc, r):
    """
    代入要測試的點座標 (x, y)
    圓心座標 (xc, yc)、半徑 r
    判斷點是否在圓形內
    """
    if (x-xc)**2 + (y-yc)**2 < r**2: return True
    return False

def in_triangle(x, y, xA, yA, xB, yB, xC, yC):
    """
    代入要測試的點座標 (x, y)
    三角形頂點座標 (xA, yA), (xB, yB), (xC, yC)
    判斷點是否在三角形內
    """
    u = ((xB - xA)*(y - yA) - (yB - yA)*(x - xA)) / ((xB - xA)*(yC - yA) - (yB - yA)*(xC - xA))
    v = ((xC - xA)*(y - yA) - (yC - yA)*(x - xA)) / ((xC - xA)*(yB - yA) - (yC - yA)*(xB - xA))
    w = 1 - u - v
    if 0 <= u <= 1 and 0 <= v <= 1 and 0 <= w <= 1: return True
    return False

""" 讀取形狀 """
figures = [[]]
for line in sys.stdin:
    if line.strip() == "*": break
    data = line.split()
    if data[0] == "r":
        figures.append([0] + list(map(float, data[1:])))
    elif data[0] == "c":
        figures.append([1] + list(map(float, data[1:])))
    else:
        figures.append([2] + list(map(float, data[1:])))

""" 判斷點是否在圖形內並組合答案 """
result = []
i = 0
n = len(figures)
for line in sys.stdin:
    if line.strip() == "9999.9 9999.9": break
    i += 1
    state = False
    x, y = map(float, line.split())
    for j in range(1, n):
        if figures[j][0] == 0:
            if in_rectangle(x, y, figures[j][1], figures[j][2], figures[j][3], figures[j][4]):
                result.append(f"Point {i:d} is contained in figure {j:d}\n")
                state = True
        elif figures[j][0] == 1:
            if in_circle(x, y, figures[j][1], figures[j][2], figures[j][3]):
                result.append(f"Point {i:d} is contained in figure {j:d}\n")
                state = True
        else:
            if in_triangle(x, y, figures[j][1], figures[j][2], figures[j][3], figures[j][4], figures[j][5], figures[j][6]):
                result.append(f"Point {i:d} is contained in figure {j:d}\n")
                state = True
    if not state:
        result.append(f"Point {i:d} is not contained in any figure\n")
sys.stdout.write("".join(result))


C++ 程式碼


2025年7月27日測試,使用時間約為 3 ms,記憶體約為 284 kB,通過測試。2026年4月6日測試,使用時間約為 1 ms,記憶體約為 3 MB,通過測試。
#include <cstdio>
#include <vector>
using namespace std;

bool in_rectangle(double x, double y, double x1, double y1, double x2, double y2) {
    /* 代入要測試的點座標 (x, y)
       長方形左上頂點座標 (x1, y1)
       長方形右下頂點座標 (x2, y2)
       判斷點是否在長方形內        */
    if (x > x1 && x < x2 && y < y1 && y > y2) return true;
    return false;
}

bool in_circle(double x, double y, double xc, double yc, double r) {
    /* 代入要測試的點座標 (x, y)
       圓心座標 (xc, yc)、半徑 r
       判斷點是否在圓形內        */
    if ((x-xc)*(x-xc) + (y-yc)*(y-yc) < r*r) return true;
    return false;
}

bool in_triangle(double x, double y, double xA, double yA, double xB, double yB, double xC, double yC) {
    /* 代入要測試的點座標 (x, y)
       三角形頂點座標 (xA, yA), (xB, yB), (xC, yC)
       判斷點是否在三角形內                        */
    double u = ((xB - xA)*(y - yA) - (yB - yA)*(x - xA)) / ((xB - xA)*(yC - yA) - (yB - yA)*(xC - xA));
    double v = ((xC - xA)*(y - yA) - (yC - yA)*(x - xA)) / ((xC - xA)*(yB - yA) - (yC - yA)*(xB - xA));
    double w = 1 - u - v;
    if (u >= 0 && u <= 1 && v >= 0 && v <= 1 && w >= 0 && w <= 1) return true;
    return false;
}

struct Obj {
    char t;
    double x1, y1, x2, y2, x3, y3, x4, y4;
};

int main() {
    /* 讀取形狀 */
    vector<Obj> figures (1);
    char t;  // 形狀的種類
    while(scanf("%c", &t) != EOF && t != '*') {
        if (t == 'r') {
            Obj tmp;
            tmp.t = 'r';
            scanf("%lf %lf %lf %lf", &tmp.x1, &tmp.y1, &tmp.x2, &tmp.y2);
            figures.push_back(tmp);
        } else if (t == 'c') {
            Obj tmp;
            tmp.t = 'c';
            scanf("%lf %lf %lf", &tmp.x1, &tmp.y1, &tmp.x2);
            figures.push_back(tmp);
        } else if (t == 't') {
            Obj tmp;
            tmp.t = 't';
            scanf("%lf %lf %lf %lf %lf %lf", &tmp.x1, &tmp.y1, &tmp.x2, &tmp.y2, &tmp.x3, &tmp.y3);
            figures.push_back(tmp);
        }
    } 
    /* 判斷點是否在圖形內並組合答案 */
    int j = 0, n = (int)figures.size();
    double x, y;
    while(scanf("%lf %lf", &x, &y) != EOF) {
        if (x > 9999.89 && x < 10000.01 && y > 9999.89 && y < 10000.01) break;
        j++;
        bool state = false;
        for(int k=1; k<=n; k++) {
            if (figures[k].t == 'r') {
                if (in_rectangle(x, y, figures[k].x1, figures[k].y1, figures[k].x2, figures[k].y2)) {
                    printf("Point %d is contained in figure %d\n", j, k);
                    state = true;
                }
            } else if (figures[k].t == 'c') {
                if (in_circle(x, y, figures[k].x1, figures[k].y1, figures[k].x2)) {
                    printf("Point %d is contained in figure %d\n", j, k);
                    state = true;
                }
            } else {
                if (in_triangle(x, y, figures[k].x1, figures[k].y1, figures[k].x2, figures[k].y2, figures[k].x3, figures[k].y3)) {
                    printf("Point %d is contained in figure %d\n", j, k);
                    state = true;
                }
            }
        }
        if (!state) printf("Point %d is not contained in any figure\n", j);
    }
    return 0;
}


沒有留言:

張貼留言