题解 | #交叉线#

交叉线

http://www.nowcoder.com/practice/54fe00d9b0e14688bd3d31ad539b929c

假设两个半圆的坐标分别是 (x1,x2), (y1, y2),其中 x2>x1 && y2>y1,那么两个圆是否相交的条件可以有:

  • y2 > x2 > y1 > x1
  • x2 > y2 > x1 > y1

这两种情况对应下面的 isInterSectAisInterSectB,这个题的空间复杂度只需要 O(1) 即上述的 4 个点即可,为了减少代码量,这里使用了数组,可以优化一下。

需要循环判断所有点,所以时间复杂度是 O(N)。

flag = flag || isInterSectA(dotVec, dotVec.size()-1) || isInterSectB(dotVec, dotVec.size()-1); 这句话将 flag 判断放到最前面,一旦出现符合的情况,之后就不再判断情况1和情况 2,稍微优化了一下。

#include <bits/stdc++.h>
using namespace std;

bool isInterSectB(vector<int> &dotVec, int i) {
    return max(dotVec[i-2], dotVec[i-3]) > max(dotVec[i], dotVec[i-1])  && 
        max(dotVec[i], dotVec[i-1]) > min(dotVec[i-2], dotVec[i-3]) && 
        min(dotVec[i-3], dotVec[i-2]) > min(dotVec[i], dotVec[i-1]);
}

bool isInterSectA(vector<int> &dotVec, int i) {
    return max(dotVec[i], dotVec[i-1]) > max(dotVec[i-2], dotVec[i-3]) && 
        max(dotVec[i-2], dotVec[i-3]) > min(dotVec[i], dotVec[i-1]) && 
        min(dotVec[i], dotVec[i-1]) > min(dotVec[i-3], dotVec[i-2]);
}


int main() {
    int sample, dotNum, dot; cin >> sample;
    while (sample--) {
        cin >> dotNum;
        vector<int> dotVec; bool flag = false;
        while (dotNum--) {
            cin >> dot;
            if (dotVec.size() < 4) {
                dotVec.push_back(dot);
            } 
            if (dotVec.size() >= 4) {
                flag = flag || isInterSectA(dotVec, dotVec.size()-1) || isInterSectB(dotVec, dotVec.size()-1);
                dotVec.push_back(dot);
            } 
        }
        cout << (flag ? "y" : "n") << endl;
    }
    return 0;
}
全部评论
平台的测例默认是半圆的左半点 < 右半点的,我的代码也是这么写的,所以这里判断 (12,2)的时候出了问题。这里只需要在调用函数之前重新确定一下半圆的边界,将 (12,2) 换成 (2,12)然后调用就行了。
1 回复 分享
发布于 2022-09-11 09:10 山东
哥们 平台测例是不是不完整, 你的代码跑这一组测例 1 12 1 3 4 5 6 7 8 9 10 11 12 2 这里的12 2 和 1 3相交了, 你的代码输出n 虽然这份代码ac了 但应该是错的
1 回复 分享
发布于 2022-09-10 22:22 陕西
29行那里重复插入了一次是为什么?
点赞 回复 分享
发布于 2023-01-14 20:13 湖南

相关推荐

03-09 20:21
门头沟学院 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务