zoj 1158 判断2线段完全相交

本文介绍了一种解决在正方形墓园中寻找特定墓碑路径的算法问题。墓园中有n面墙,需要计算从外部到达指定墓碑位置至少需要凿开几个门,且门必须位于现有线段的中点。通过计算所有可能路径与墙的交点数量来得出最优解。

一个正方形的古老墓园,有n面墙,墙的端点都在正方形的边上。已知墓碑的地点(x,y),问从外面一直到达墓碑至少要凿开几个门,而且规定门只能凿在当前点段的中点。

思路很巧妙,因为从一个点到终点不可能“绕过”围墙,只能传过去,所以门是否开在中点是无所谓的,只要求四周线段中点到终点的线段与墙的最少交点个数即可。更进一步,实际上,只需判断四周围墙的所有点与终点的连线与内墙的最少交点加一即可。


const double eps = 1e-8 ;

double  add(double x , double y){
        if(fabs(x+y) < eps*(fabs(x) + fabs(y))) return 0 ;
        return x + y ;
}

struct  Point{
        double x , y ;
        Point(){}
        Point(double _x , double _y):x(_x),y(_y){}
        Point operator + (Point o){
              return Point(add(x , o.x) , add(y , o.y)) ;
        }
        Point operator - (Point o){
              return Point(add(x , -o.x) , add(y , -o.y)) ;
        }
        Point operator * (double o){
              return Point(x*o , y*o) ;
        }
        double operator ^(Point o){
               return add(x*o.y , -y*o.x) ;
        }
        double dist(Point o){
               return sqrt((x-o.x)*(x-o.x) + (y-o.y)*(y-o.y)) ;
        }
        void  read(){
              scanf("%lf%lf" ,&x , &y) ;
        }
};

int  intersection(Point p1 , Point p2 , Point q1 , Point q2){
     double d1 = (p2 - p1) ^ (q1 - p1) ;
     double d2 = (p2 - p1) ^ (q2 - p1) ;
     double d3 = (q2 - q1) ^ (p1 - q1) ;
     double d4 = (q2 - q1) ^ (p2 - q1) ;
     return d1 * d2 < 0  &&  d3 * d4 < 0 ;
}

struct Line{
       Point s , t ;
       Line(){}
       Line(Point _s , Point _t):s(_s),t(_t){}
       int intersect(Line o){ // 直线与线段O是否相交
           return intersection(s , t , o.s , o.t) ;
       }
       void read(){
            s.read() , t.read() ;
       }
       friend bool operator < (const Line A ,const Line B){
            return A.s.x < B.s.x ;
       }
};

vector<Line> lisline  ;
vector<Point> lispoint  ;

int  main(){
     int t  , k  , n , i  , j  , T = 1 ;
     Point  ed  , ls , ld ;
     cin>>t ;
     while(t--){
          cin>>n ;
          lispoint.clear() ;
          lisline.clear() ;
          lispoint.push_back(Point(0.0 , 0.0)) ;
          lispoint.push_back(Point(0.0 , 100.0)) ;
          lispoint.push_back(Point(100.0 , 0.0)) ;
          lispoint.push_back(Point(100.0 , 100.0)) ;
          for(i = 1 ; i <= n ; i++){
              ls.read() , ld.read() ;
              lispoint.push_back(ls) ;
              lispoint.push_back(ld) ;
              lisline.push_back(Line(ls , ld))  ;
          }
          ed.read() ;
          int  ans = 100000000  , sum ;
          for(i = 0 ; i < lispoint.size() ; i++){
                Line now = Line(lispoint[i] , ed) ;
                sum = 0 ;
                for(j = 0 ; j < lisline.size() ; j++){
                      if(now.intersect(lisline[j]))  sum++ ;
                }
                ans = min(ans , sum) ;
          }
          if(T != 1) puts("") ;
          T++ ;
          printf("Number of doors = %d\n" , ans+1) ;
     }
     return 0 ;
}


(1)普通用户端(全平台) 音乐播放核心体验: 个性化首页:基于 “听歌历史 + 收藏偏好” 展示 “推荐歌单(每日 30 首)、新歌速递、相似曲风推荐”,支持按 “场景(通勤 / 学习 / 运动)” 切换推荐维度。 播放页功能:支持 “无损音质切换、倍速播放(0.5x-2.0x)、定时关闭、歌词逐句滚动”,提供 “沉浸式全屏模式”(隐藏冗余控件,突出歌词与专辑封面)。 多端同步:自动同步 “播放进度、收藏列表、歌单” 至所有登录设备(如手机暂停后,电脑端打开可继续播放)。 音乐发现与管理: 智能搜索:支持 “歌曲名 / 歌手 / 歌词片段” 搜索,提供 “模糊匹配(如输入‘晴天’联想‘周杰伦 - 晴天’)、热门搜索词推荐”,结果按 “热度 / 匹配度” 排序。 歌单管理:创建 “公开 / 私有 / 加密” 歌单,支持 “批量添加歌曲、拖拽排序、一键分享到社交平台”,系统自动生成 “歌单封面(基于歌曲风格配色)”。 音乐分类浏览:按 “曲风(流行 / 摇滚 / 古典)、语言(国语 / 英语 / 日语)、年代(80 后经典 / 2023 新歌)” 分层浏览,每个分类页展示 “TOP50 榜单”。 社交互动功能: 动态广场:查看 “关注的用户 / 音乐人发布的动态(如‘分享新歌感受’)、好友正在听的歌曲”,支持 “点赞 / 评论 / 转发”,可直接点击动态中的歌曲播放。 听歌排行:个人页展示 “本周听歌 TOP10、累计听歌时长”,平台定期生成 “全球 / 好友榜”(如 “好友中你本周听歌时长排名第 3”)。 音乐圈:加入 “特定曲风圈子(如‘古典音乐爱好者’)”,参与 “话题讨论(如‘你心中最经典的钢琴曲’)、线上歌单共创”。 (2)音乐人端(创作者中心) 作品管理: 音乐上传:支持 “无损音频(FLAC/WAV)+ 歌词文件(LRC)+ 专辑封面” 上传,填写 “歌曲信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值