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

  • 相关阅读:
    Oracle SQL语句收集
    SqlParameter In 查询
    SQL 性能优化
    Entity Framework
    【XLL API 函数】 xlfSetName
    【XLL API 函数】xlfUnregister (Form 2)
    【XLL API 函数】xlfUnregister (Form 1)
    【Excel 4.0 函数】REGISTER 的两种形式以及VBA等效语句
    【Excel 4.0 函数】REGISTER
    【Bochs 官方手册翻译】 第一章 Bochs介绍
  • 原文地址:https://www.cnblogs.com/wsy107316/p/13550173.html
Copyright © 2011-2022 走看看