1 条题解

  • 0
    @ 2025-4-8 19:22:47

    题意分析

    该题的核心是折叠,这涉及到直线和点之间的关系,该题给出折叠次数,以其一个折叠后的坐标,要求出有多少个点通过折叠可以到达这个坐标

    解题思路

    该题的核心重点在于直线对折,在二维平面中,直线的一般式方程为 Ax+By+C=0Ax+By+C=0 其中 p1 p2 为直线上的两个点 a=p2.yp1.ya = p2.y - p1.y, b=p1.xp2.xb = p1.x - p2.x c=(ap1.x+bp1.y)c = -(a * p1.x + b * p1.y) a,b之间距离 denominator=aa+bbdenominator = a * a + b * b 点p到直线距离 val=ap.x+bp.y+cval = a * p.x + b * p.y + c 由此可算出p点坐标 x_reflect = p.x2aval/denominatorp.x - 2 * a * val / denominator

    y_reflect = p.y2bval/denominatorp.y - 2 * b * val / denominator 考虑到从第一条折叠计算点的坐标非常复杂,我们已知折叠到最后点的坐标,不妨反过来从最后点的坐标来求前面可能被折叠的点的坐标。 而如果折叠后的点在直线上或在折叠线右边,则这个点应该舍去,我们只需要在折叠线右边的点,而叉积可以帮助我们。 对于直线上的两个点a,b。直线外一点c 他们的叉积为 $(b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)$ 如果叉积大于0.表明c在直线左侧,这就是我们要找的点

    标程

    ```cpp
    #include <iostream>
    #include <vector>
    #include <cmath>
    using namespace std;
    const double EPS = 1e-7;
    struct Point{
        double x,y;
        Point(double x = 0,double y = 0) : x(x),y(y){}
    };
    double cross(const Point& a,const Point& b, const Point& c){
        return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
    }
    Point reflectPoint(const Point& p1, const Point& p2, const Point& p){
        double a = p2.y - p1.y;
        double b = p1.x - p2.x;
        double c = -(a * p1.x + b * p1.y);
        double denominator = a * a + b * b;
        if(std::abs(denominator) < EPS){
            return p;
        }
        double val = a * p.x + b * p.y + c;
        double x_reflect = p.x - 2 * a * val / denominator;
        double y_reflect = p.y - 2 * b * val / denominator;
        Point newp = Point(x_reflect,y_reflect);
        return newp;
    }
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cout.tie(0);
        int n_folds;
        cin >> n_folds;
        vector<pair<Point,Point>> folds(n_folds);
        for(int i = 0; i < n_folds; i++){
            double x1,x2,y1,y2;
            cin >> x1 >> y1 >> x2 >> y2;
            folds[i] = {Point(x1,y1),Point(x2,y2)};
        }
        int n_queries;
        cin >> n_queries;
        for(int i = 0; i < n_queries; i++){
            double x,y;
            cin>> x >> y;
            vector<Point> points = {Point(x,y)};
            for(int j = n_folds - 1; j >= 0; j--){
                auto [p1,p2] = folds[j];
                vector<Point> new_points;
                for(const Point& p : points){
                    double d = cross(p1,p2,p);
                    if(std::abs(d) <= EPS){
                        continue;
                    }
                    if(d > EPS){
                        new_points.push_back(p);
                        Point newp = reflectPoint(p1,p2,p);
                        new_points.push_back(newp);
                    }
                }
                points = new_points;
            }
            int count = 0;
            for (const Point& p : points) {
                if (p.x > EPS && p.x < 100 - EPS && p.y > EPS && p.y < 100 - EPS) {
                    count++;
                }
            }
            cout << count << endl;
        }
        return 0;
    }    
    
    • 1

    信息

    ID
    1617
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    3
    已通过
    1
    上传者