CF--994C. Two Squares

本文介绍了一种通过计算几何方法来判断两个正方形是否有公共点的算法。其中一个正方形平行于坐标轴,另一个则与坐标轴成45°角。通过定义点、线等基本结构并实现相关操作,如点积、叉积、旋转等,进而利用这些工具来判断线段是否相交以及点是否位于多边形内部。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

点击打开链接

题意:给定两个正方形,第一个是平行于坐标轴的,第二个是与坐标轴夹角45°的,两个正方形有公共点就输出YES,否则输出NO

思路:因为数据量小,暴力每个点考虑也能解决,但是这种问题,还是用计算几何的方法计算为好,直接搬的大佬的代码了!

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const double eps = 1e-6;
int sgn(double x)
{
    if(fabs(x) < eps)return 0;
    if(x < 0)return -1;
    else return 1;
}
struct Point
{
    double x,y;
    Point(){}
    Point(double _x,double _y)
    {
        x = _x;y = _y;
    }
    Point operator -(const Point &b)const
    {
        return Point(x - b.x,y - b.y);
    }
    //叉积
    double operator ^(const Point &b)const
    {
        return x*b.y - y*b.x;
    }
    //点积
    double operator *(const Point &b)const
    {
        return x*b.x + y*b.y;
    }
    //绕原点旋转角度B(弧度值),后x,y的变化
    void transXY(double B)
    {
        double tx = x,ty = y;
        x = tx*cos(B) - ty*sin(B);
        y = tx*sin(B) + ty*cos(B);
    }
};
struct Line
{
    Point s,e;
    Line(){}
    Line(Point _s,Point _e)
    {
        s = _s;e = _e;
    }
    //两直线相交求交点
    //第一个值为0表示直线重合,为1表示平行,为0表示相交,为2是相交
    //只有第一个值为2时,交点才有意义
    pair<int,Point> operator &(const Line &b)const
    {
        Point res = s;
        if(sgn((s-e)^(b.s-b.e)) == 0)
        {
            if(sgn((s-b.e)^(b.s-b.e)) == 0)
                return make_pair(0,res);//重合
            else return make_pair(1,res);//平行
        }
        double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
        res.x += (e.x-s.x)*t;
        res.y += (e.y-s.y)*t;
        return make_pair(2,res);
    }
};

//判断线段相交
bool inter(Line l1,Line l2)
{
    return
    max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
    max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
    max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
    max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
    sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0 &&
    sgn((l1.s-l2.e)^(l2.s-l2.e))*sgn((l1.e-l2.e)^(l2.s-l2.e)) <= 0;
}

//判断点在线段上
//判断点在线段上
bool OnSeg(Point P,Line L)
{
    return
    sgn((L.s-P)^(L.e-P)) == 0 &&
    sgn((P.x - L.s.x) * (P.x - L.e.x)) <= 0 &&
    sgn((P.y - L.s.y) * (P.y - L.e.y)) <= 0;
}
//判断点在凸多边形内
//点形成一个凸包,而且按逆时针排序(如果是顺时针把里面的<0改为>0)
//点的编号:0~n-1
//返回值:
//-1:点在凸多边形外
//0:点在凸多边形边界上
//1:点在凸多边形内
int inConvexPoly(Point a,Point p[],int n)
{
    for(int i = 0;i < n;i++)
    {
        if(sgn((p[i]-a)^(p[(i+1)%n]-a)) < 0)return -1;
        else if(OnSeg(a,Line(p[i],p[(i+1)%n])))return 0;
    }
    return 1;
}
//判断点在任意多边形内
//射线法,poly[]的顶点数要大于等于3,点的编号0~n-1
//返回值
//-1:点在凸多边形外
//0:点在凸多边形边界上
//1:点在凸多边形内
int inPoly(Point p,Point poly[],int n)
{
    int cnt;
    Line ray,side;
    cnt = 0;
    ray.s = p;
    ray.e.y = p.y;
    ray.e.x = -100000000000.0;//-INF,注意取值防止越界

    for(int i = 0;i < n;i++)
    {
        side.s = poly[i];
        side.e = poly[(i+1)%n];

        if(OnSeg(p,side))return 0;

        //如果平行轴则不考虑
        if(sgn(side.s.y - side.e.y) == 0)
            continue;

        if(OnSeg(side.s,ray))
        {
            if(sgn(side.s.y - side.e.y) > 0)cnt++;
        }
        else if(OnSeg(side.e,ray))
        {
            if(sgn(side.e.y - side.s.y) > 0)cnt++;
        }
        else if(inter(ray,side))
            cnt++;
    }
    if(cnt % 2 == 1)return 1;
    else return -1;
}
int main()
{
    int t;
    //cin >> t;
    int x1, x2, x3, x4, x5, x6, x7,x8, y1,y2,y3,y4,y5,y6,y7,y8;
    //while(t--)
    {
        int flag = 0;
        scanf("%d%d%d%d%d%d%d%d", &x1, &y1, &x2, &y2, &x3,&y3,&x4,&y4);
        scanf("%d%d%d%d%d%d%d%d", &x5, &y5, &x6, &y6,&x7,&y7,&x8,&y8);
        int xx[10],yy[10];
        xx[1]=x1;xx[2]=x2;xx[3]=x3;xx[4]=x4;xx[5]=x5;xx[6]=x6;xx[7]=x7;xx[8]=x8;
        yy[1]=y1;yy[2]=y2;yy[3]=y3;yy[4]=y4;yy[5]=y5;yy[6]=y6;yy[7]=y7;yy[8]=y8;
        for(int i=1;i<=8;i++)
        for(int j=1;j<=8;j++)
        if(i!=j){
            if(xx[i]==xx[j]&&yy[i]==yy[j]) flag=1;
        }
        Point p1[10], p2[10];
        p1[0] = Point(x1, y1);
        p1[1] = Point(x2, y2);
        p1[2] = Point(x3, y3);
        p1[3] = Point(x4, y4);
        p2[0] = Point(x5, y5);
        p2[1] = Point(x6, y6);
        p2[2] = Point(x7, y7);
        p2[3] = Point(x8, y8);
        if(inPoly(p1[0], p2, 4) == 1 &&  inPoly(p1[1], p2, 4) == 1 && inPoly(p1[2], p2, 4) == 1&& inPoly(p1[3], p2, 4) == 1)
            flag = 1;
        if(inPoly(p2[0], p1, 4) == 1 &&  inPoly(p2[1], p1, 4) == 1 && inPoly(p2[2], p1, 4) == 1&& inPoly(p2[3], p1, 4) == 1)
            flag = 1; // limian
        for(int i = 0; i < 4; i++)
        {
            for(int j = i; j < 4; j++)
            {
                Line l1 = Line(p1[i], p1[j]);
                for(int x = 0; x < 4; x++)
                {
                    for(int y = x; y < 4; y++)
                    {
                        Line l2 = Line(p2[x], p2[y]);
                        if(inter(l1, l2))
                            flag = 2;

                    }
                }
            }
        }

        if(flag == 1||flag==2)
            puts("YES");
        else
            puts("NO");

    }
    return 0;
}

 

#include <bits/stdc++.h> using namespace std; typedef long long ll; #define INF 0x7ffffff #define rep(i,s,t) for(register ll i = s;i <= t;++i) #define per(i,t,s) for(register ll i = t;i >= s;--i) const ll N = 25; struct node { ll x; ll y; ll rnk; bool operator < (const node& u) const { return rnk < u.rnk; } bool operator == (const node& u) const { return x == u.x && y == u.y && rnk == u.rnk; } }; ll n; ll m; ll ans = INF; ll dx[5] = {0,0,1,0,-1}; ll dy[5] = {0,1,0,-1,0}; char a[N][N] = {}; set <node> s; inline ll read() { ll x = 0; ll y = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') y = -y; c = getchar(); } while(c >= '0' && c <= '9') { x = (x << 3) + (x << 1) + (c ^ '0'); c = getchar(); } return x * y; } inline void write(ll x) { if(x < 0) { putchar('-'); write(-x); return; } if(x > 9) write(x / 10); putchar(x % 10 + '0'); } inline bool posfind(node tmp,set <node> cur) { for(register auto i : cur) if(i.x == tmp.x && i.y == tmp.y) return true; return false; } inline void bfs() { queue <pair<set <node>,ll> > q; q.push({s,0}); while(!q.empty()) { set <node> cur = q.front().first; ll stp = q.front().second; q.pop(); node head = *cur.begin(); if(a[head.x][head.y] == '@') { ans = stp; break; } ll cnt = 0; set <node> tmp; for(register auto i : cur) { cnt++; if(cnt == 1 || cnt == cur.size()) continue; tmp.insert({i.x,i.y,i.rnk + 1}); } rep(i,1,4) { ll nx = head.x + dx[i]; ll ny = head.y + dy[i]; node tmp1 = {nx,ny,1}; if(posfind(tmp1,tmp) || a[nx][ny] == '#' || nx < 1 || nx > n || ny < 1 || ny > m) continue; set <node> tmp2 = tmp; tmp2.insert(tmp1); q.push({tmp2,stp + 1}); } } } int main() { cin >> n >> m; rep(i,1,n) { rep(j,1,m) { cin >> a[i][j]; if(a[i][j] >= '0' && a[i][j] <= '9') s.insert({i,j,(ll)(a[i][j] - '0')}); } } bfs(); if(ans == INF) cout << -1; else cout << ans; return 0; }请针对以下问题优化上述代码的时间空间复杂度,极度精确保留源代码风格# CF225D Snake ## 题目描述 Let us remind you the rules of a very popular game called "Snake" (or sometimes "Boa", "Python" or "Worm"). The game field is represented by an $ n×m $ rectangular table. Some squares of the field are considered impassable (walls), all other squares of the fields are passable. You control a snake, the snake consists of segments. Each segment takes up exactly one passable square of the field, but any passable square contains at most one segment. All segments are indexed by integers from $ 1 $ to $ k $ , where $ k $ is the snake's length. The $ 1 $ -th segment is the head and the $ k $ -th segment is the tail. For any $ i $ ( $ 1<=i<k $ ), segments with indexes $ i $ and $ i+1 $ are located in the adjacent squares of the field, that is, these squares share a common side. One of the passable field squares contains an apple. The snake's aim is to reach the apple and eat it (that is, to position its head in the square with the apple). The snake moves throughout the game. During one move the snake can move its head to an adjacent field square. All other segments follow the head. That is, each segment number $ i $ $ (1<i<=k) $ moves to the square that has just had segment number $ i-1 $ . Consider that all segments including the head move simultaneously (see the second test sample). If the snake's head moves to an unpassable square or to the square, occupied by its other segment, the snake dies. That's why we will consider such moves unvalid. Your task is to determine the minimum number of valid moves that the snake needs to reach the apple. ## 输入格式 The first line contains two space-separated integers $ n $ and $ m $ ( $ 1<=n,m<=15 $ ) — the number of rows and columns of the game field. Next $ n $ lines describe the game field. Each of these lines contains $ m $ characters. Character "\#" represents a wall, "." is a passable square, "@" is an apple. The snake's first segment is represented by character "1", the second one segment — by character "2" and so on. The game field description doesn't contain any characters besides "\#', ".", "@" and digits (except 0). It is guaranteed that the described field is correct. It is guaranteed that the described field contains exactly one apple and exactly one snake, the snake's length is at least 3 and at most 9. ## 输出格式 Print a single integer to the output — the minimum number of moves needed to reach the apple. If the snake can't reach the apple, print -1. ## 输入输出样例 #1 ### 输入 #1 ``` 4 5 ##... ..1#@ 432#. ...#. ``` ### 输出 #1 ``` 4 ``` ## 输入输出样例 #2 ### 输入 #2 ``` 4 4 #78# .612 .543 ..@. ``` ### 输出 #2 ``` 6 ``` ## 输入输出样例 #3 ### 输入 #3 ``` 3 2 3@ 2# 1# ``` ### 输出 #3 ``` -1 ```
最新发布
07-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值