Liaoning Ship’s Voyage
, which named after a province of China, is the first aircraft carrier commissioned into the It was bought from as a stripped hulk and was rebuilt by China as an important part of China’s blue water Navy plan. Liaoning ship has sailed far into the Pacific Ocean for serval times, which shows the power and resolve of China to defend her integrity of territory.
Now is on a new voyage to the Atlantic Ocean for a maneuver! The vast maneuver region on the ocean can be seen as an grid which has crosspoints. Each crosspoint stands for a check point of the maneuver region. Liaoning starts from the bottom-left check point whose coordinate is , and its destination is the upper-right checkpoint whose coordinate is The positive side of the axis points to the right, and the positive side of the y axis points up. All check points’ coordinates are integral. During each move, can go from one check point to its adjacent check points along a straight line, and each move takes one day. Some check points are not available to go due to the bad weather. And, as you know, on the Atlantic Ocean, there is a Bermuda Triangle in which many ships and planes were missing. can’t take risk to go into that triangle. Of course, Liaoning can’t go outside the maneuver region. Please figure out a route for Liaoning to reach its destination as soon as possible.
Input
There are no more than test cases.
For each case:
The first line is an integer meaning that the maneuver region is an grid.
The seconds line contains six float numbers which have at most digits after the decimal point, indicating the coordinates of the vertices of Bermuda Triangle are and Liaoning ship can’t go into that triangle, but going along its edges or touching its vertices are allowed.
Then an n×n character matrix consists of ‘.’ and ‘#’ follows, indicating the weather condition of all check points. ‘.’ Means good weather and ‘#’ means bad weather. The bottom-left character stands for the weather of check point the character on the right side of it stands for and the upper-right character stands for
It is guaranteed that check point is not inside the Bermuda Triangle or on the edges of the triangle.
Output
For each test case, print the minimum days Liaoning ship needs to reach its destination. If it is impossible for Liaoning to reach its destination, print -1 instead.
Sample Input
3
0.5 1.5 1.5 1.5 1 0.5
.#.
...
..#
3
0.5 1.5 1.5 1.5 1 0.5
.#.
..#
..#
Sample Output
3
-1
題意
- 就是說有一個地圖,你需要從走到,每次你可以向相鄰的八個整點沿直線走,時間花費都是,不能走到’#'中,而且走的路徑不能到達給定的一個三角形中,但是可以沿着三角形的一條邊走或者經過一個頂點,然後求最小的從走到的時間
題解
- 很小,考慮暴力找出所有可行路徑然後
- 重點以及難點就是判斷一條路徑是否與在內部有公共點,步驟如下
- 首先如果兩個點和都在內部的話(可以根據三個小三角形面積之和等於大三角形面積),進一步判斷一下兩個點是否都在三角形的某一條邊上,如果是,則合法,否則不合法
- 現在主要考慮枚舉三角形的每一條邊與求交,如果沒有交點或者平行或者重合,繼續枚舉,否則剩下的情況就是不平行而且相交的情況,求出交點,如果交點不等於任何一個線段端點,這時可以直接判定在三角形內部有公共點,那麼顯然不合法,否則的話如果交點等於三角形的一個頂點,那麼也就是下圖這種情況
直接判斷與大小即可判斷是否相交
代碼
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-8;
const int maxn=50;
#define pi acos(-1.0)
int sgn(double k) {return k<-eps?-1:(k<eps?0:1);}
double Acos(double k) {return k>=1?0:(k<=-1?pi:acos(k));}
double Sqrt(double k) {return sgn(k)<=0?0:sqrt(k);}
char s[maxn][maxn];
bool vis[maxn][maxn];
bool ok[25][25][25][25];
int n,dir[8][2]={{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0}};
struct point{
double x,y;
point(double a=0,double b=0) {x=a;y=b;}
point operator+(point other) {return point(x+other.x,y+other.y);}
point operator-(point other) {return point(x-other.x,y-other.y);}
point operator*(double k) {return point(x*k,y*k);}
friend bool operator==(const point &p1,const point &p2) {return sgn(p1.x-p2.x)==0&&sgn(p1.y-p2.y)==0;}
double operator*(point other) {return x*other.x+y*other.y;}
double operator^(point other) {return x*other.y-y*other.x;}
friend double area(point a,point b,point c) {return fabs((b-a)^(c-a))/2;}
friend int point_to_line(point p,point s,point e) {return -sgn((e-s)^(p-s));}
friend double len(point p) {return Sqrt(p.x*p.x+p.y*p.y);}
friend double angle(point p1,point p2) {
if(point_to_line(p2,point(0,0),p1)<=0) return Acos((p1*p2)/len(p1)/len(p2));
return 2*pi-Acos((p1*p2)/len(p1)/len(p2));
}
};
struct line{
point s,e;
line () {}
line (point a,point b) {s=a;e=b;}
friend point intersect(line l1,line l2) {
double k=((l2.e-l2.s)^(l2.s-l1.s))/((l2.e-l2.s)^(l1.e-l1.s));
return l1.s+(l1.e-l1.s)*k;
}
friend bool onseg(point p,line l) {
return sgn((l.s-p)^(l.e-p))==0&&sgn((l.s-p)*(l.e-p))<=0;
}
friend int seg_to_seg(line l1,line l2) {
if(sgn((l1.e-l1.s)^(l2.e-l2.s))==0) {
if(onseg(l1.s,l2)||onseg(l1.e,l2)||onseg(l2.s,l1)||onseg(l2.e,l1)) return 1;
return 0;
}
point inter=intersect(l1,l2);
if(onseg(inter,l1)&&onseg(inter,l2)) return 3;
return 2;
}
friend bool onright(point p,line l) {return ((l.e-l.s)^(p-l.s))<=0;}
};
point p[3];
line l[3];
struct node{int x,y,step;};
bool valid(int x,int y) {return x>=0&&x<=n-1&&y>=0&&y<=n-1&&s[x][y]!='#'&&!vis[x][y];}
int bfs() {
memset(vis,false,sizeof(vis));
queue<node> que;
if(s[0][0]=='#'||s[n-1][n-1]=='#') return -1;
que.push(node{0,0,0});
vis[0][0]=true;
while(!que.empty()) {
node cur=que.front();que.pop();
for(int i=0;i<8;i++) {
int nxtx=cur.x+dir[i][0],nxty=cur.y+dir[i][1];
if(valid(nxtx,nxty)&&ok[cur.x][cur.y][nxtx][nxty]) {
vis[nxtx][nxty]=true;
que.push(node{nxtx,nxty,cur.step+1});
if(nxtx==n-1&&nxty==n-1) return cur.step+1;
}
}
}
return -1;
}
bool point_in_triangle(point p,point a,point b,point c) {
return sgn(area(p,a,b)+area(p,b,c)+area(p,c,a)-area(a,b,c))==0;
}
bool zhongjian(point p,point a,point o,point b) {
double k1=angle(b-o,p-o);
double k2=angle(b-o,a-o);
return sgn(k1)>0&&sgn(k1-k2)<0;
}
bool check(int a,int b,int c,int d) {
bool ok1=a>=0&&a<=n-1&&b>=0&&b<=n-1&&c>=0&&c<=n-1&&d>=0&&d<=n-1&&s[a][b]!='#'&&s[c][d]!='#';
if(!ok1) return false;
point p1=point(a,b),p2=point(c,d);
if(point_in_triangle(p1,p[0],p[1],p[2])&&point_in_triangle(p2,p[0],p[1],p[2])) {
bool ok=false;
for(int i=0;i<=2;i++) if(onseg(p1,l[i])&&onseg(p2,l[i])) {ok=true;break;}
return ok;
}
for(int i=0;i<=2;i++) {
int k=seg_to_seg(line(p1,p2),l[i]);
if(k==3){
point inter=intersect(line(p1,p2),l[i]);
if(!(inter==p1||inter==p2||inter==l[i].s||inter==l[i].e)) return false;
else if(inter==p[i]) {
if(inter==p1||inter==p2) continue;
if(zhongjian(p1,p[((i-1)+3)%3],p[i],p[(i+1)%3])||zhongjian(p2,p[((i-1)+3)%3],p[i],p[(i+1)%3])) return false;
}
}
}
return true;
}
int main() {
while(~scanf("%d",&n)) {
memset(ok,false,sizeof(ok));
for (int i = 0; i <= 2; i++) scanf("%lf %lf",&p[i].x,&p[i].y);
if(onright(p[2],line(p[0],p[1]))) swap(p[1],p[2]);
for(int i=0;i<=2;i++) l[i]=line(p[i],p[(i+1)%3]);
for(int j=n-1;j>=0;j--) for(int i=0;i<=n-1;i++) scanf(" %c",&s[i][j]);
for(int i=0;i<=n-1;i++) {
for(int j=0;j<=n-1;j++) {
for (int k = 0; k < 8; k++) {
int nxtx =i+dir[k][0],nxty=j+dir[k][1];
if(check(i,j,nxtx,nxty)) {
ok[i][j][nxtx][nxty]=ok[nxtx][nxty][i][j]=true;
}
}
}
}
printf("%d\n",bfs());
}
}