zoukankan      html  css  js  c++  java
  • Liaoning Ship’s Voyage(计算几何:点在三角形内的判定+线段穿过三角形的判定)

    Liaoning Ship’s Voyage

    题意:在一个(n*n)的区域内,"."可以走,"#"不可以走,同时给定三个点,这三个点围成的三角形区域也是不可以走的。船的起始位置在(0,0)处(左下角),终点在(n-1,n-1)(右上角),问小船从起始位置到终点所要花费的最小时间。

    题解:对每个点标号,建图,用(bfs)跑出最短路。连边时要判断路线是否穿过三角形,具体方法是,在路线上平均取1000个点,若1000个点都不在三角形中,则认为该路线没有穿过三角形。

    AC_Code:(注意代码中num数组的num[i][j]不对应坐标系中的(i,j)点,对应的是(j,i)点,注意体会一下)

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 #define endl '
    '
      5 const ll inf = 0x3f3f3f3f3f3f3f3f;
      6 const int maxn = 110;
      7 const double eps = 1e-7;
      8 
      9 
     10 struct Point{
     11     double x,y;
     12     Point(double x=0, double y=0):x(x),y(y){}
     13 };
     14 
     15 typedef Point Vector;
     16 Vector operator+(Vector A, Vector B) { return Vector(A.x+B.x,A.y+B.y); }
     17 Vector operator-(Vector A, Vector B) { return Vector(A.x-B.x,A.y-B.y); }
     18 Vector operator*(Vector A, double B) { return Vector(A.x*B,A.y*B); }
     19 Vector operator/(Vector A, double B) { return Vector(A.x/B,A.y/B); }
     20 
     21 int sgn(double x){
     22     if( fabs(x)<eps ) return 0;
     23     else if( x<0 ) return -1;
     24     else return 1;
     25 }
     26 
     27 bool operator <(const Point &a, const Point &b){
     28     if( a.x==b.x ) return a.y<b.y;
     29     return a.x<b.x;
     30 }
     31 bool operator == (const Point &a,const Point &b){
     32     if( sgn(a.x-b.x)==0 && sgn(a.y-b.y)==0 ) return true;
     33     return false;
     34 }
     35 
     36 double Dot(Vector A, Vector B) { return A.x*B.x+A.y*B.y; }
     37 double Length(Vector A) { return sqrt(Dot(A,A));}
     38 double Cross(Vector A, Vector B) { return A.x*B.y-A.y*B.x; }
     39 
     40 int n,en;
     41 int num[22][22];
     42 char x[22];
     43 int dirx[8] = {0,1,1,1,0,-1,-1,-1};
     44 int diry[8] = {1,1,0,-1,-1,-1,0,1};
     45 vector<int>G[410];
     46 Point a[4];
     47 int _time[410],f[410];
     48 
     49 bool isPointInPolygon(Point p){//点在三角形内的判定
     50     return sgn(Cross(a[1]-a[0],p-a[0]))>0 && sgn(Cross(a[2]-a[1],p-a[1]))>0 && sgn(Cross(a[0]-a[2],p-a[2]))>0;
     51 }
     52 
     53 bool check(Point x,Point y){//两点之间连边时判断是否穿过三角形,具体方法:在路线上平均取1000个点,若1000个点都不在三角形内,则认为该路线没有穿过三角形
     54     for(int i=1;i<=1000;i++){
     55         Point t=x+(y-x)/1000.0*(double)i;
     56         if( isPointInPolygon(t)==1 ) return false;
     57     }
     58     return true;
     59 }
     60 
     61 int bfs(int n){
     62     queue<int>q;
     63     for(int i=1;i<=n;i++) _time[i]=1000000;
     64     while( !q.empty() ) q.pop();
     65     q.push(1);
     66     f[1]=true;
     67     _time[1]=0;
     68 
     69     while( !q.empty() ){
     70         int x=q.front(); q.pop();
     71         for(int i=0; i<G[x].size(); i++){
     72             int v=G[x][i];
     73             if( _time[x]+1<_time[v] ){
     74                 _time[v]=_time[x]+1;
     75                 if( !f[v] ){
     76                     q.push(v);
     77                     f[v]=true;
     78                 }
     79             }
     80         }
     81     }
     82     if( _time[en]==1000000 ) return -1;
     83     else return _time[en];
     84 }
     85 
     86 
     87 int main()
     88 {
     89     while( ~scanf("%d",&n)){
     90         memset(num,0,sizeof(num));
     91         memset(G,0,sizeof(G));
     92         memset(f,false,sizeof(f));
     93 
     94         for(int i=0;i<3;i++)
     95             scanf("%lf%lf",&a[i].x,&a[i].y);
     96 
     97         if( sgn(Cross(a[1]-a[0],a[2]-a[0]))<0 ) //向量02在向量01的顺时针方向
     98             swap(a[1],a[2]);//交换使得按0,1,2的顺序是逆时针
     99 
    100         for(int i=n-1;i>=0;i--){
    101             scanf("%s",x);
    102             for(int j=0;j<n;j++){
    103                 if( x[j]=='#' || isPointInPolygon(Point(j,i))==1 )
    104                     num[i][j]=-1;
    105             }
    106         }
    107         int t=0;
    108         for(int i=0;i<n;i++){
    109             for(int j=0;j<n;j++){
    110                 if( num[i][j]!=-1 )
    111                     num[i][j]=++t;
    112             }
    113         }
    114 
    115         for(int i=0;i<n;i++){
    116             for(int j=0;j<n;j++){
    117                 if( num[i][j]!=-1 ){
    118                     for(int k=0;k<8;k++){
    119                         int x=i+dirx[k];
    120                         int y=j+diry[k];
    121                         if( !(x>=0 && x<n && y>=0 && y<n && num[x][y]!=-1) ) continue;
    122                         if( check(Point(j,i),Point(y,x))){
    123                             int u=num[i][j];
    124                             int v=num[x][y];
    125                             G[u].push_back(v);
    126                         }
    127                     }
    128                 }
    129             }
    130         }
    131 
    132         en = num[n-1][n-1];
    133         if( en==-1 ) printf("-1
    ");
    134         else printf("%d
    ",bfs(en));
    135     }
    136     return 0;
    137 }

    大佬博客:here

  • 相关阅读:
    vue脚手架项目配置后端接口(mock数据)
    list添加删除动画(transition-group)
    fast mock官网mock数据
    vuex日志插件(createLogger)
    环形进度条
    程序员的周末生活
    hbase错误之Region in transition异常解决
    不同虚拟机之间的文件传递
    windows上链接虚拟机
    hadoop——yarn
  • 原文地址:https://www.cnblogs.com/wsy107316/p/13550173.html
Copyright © 2011-2022 走看看