规避

题目描述
2014 年7 月17 日,马来西亚航空MH17 班机执飞阿姆斯特丹史基浦机场飞往吉隆坡国际机场航线时,在乌克兰靠近俄罗斯边界33,000 英尺高空疑受到9K37 山毛榉地对空导弹击落坠毁。事件发生后,汉莎航空、法国航空、土耳其航空、俄罗斯洲际航空、达美航空、英国航空、俄罗斯航空、印度航空、捷特航空和荷兰皇家航空开始禁止班机进入乌克兰东部或全境领空范围。美国航空公司的班机禁止在乌克兰境内飞行,同时UTair 航空、意大利航空和维珍航空也宣布他们的班机将会重新规划航行的路线。英国交通部已经要求该国的班机不要进入乌克兰领空范围。中国民用航空局已要求国内航空公司所有飞越乌克兰的航班绕飞。
作为相关负责人,你需要根据实际情况规划航线规避不安全地区,包括战争区域、危险天气、火山灰和外星人入侵……等。每个不安全区域被标记为一个凸多边形,每个凸多边形相离,你需要规划一条从指定起点到指定终点的航线,要求航线不得进入不安全区域,输出它的最短长度。为了你的方便,起点和终点都是多边形的顶点。
输入
第一行一个整数N 表示不安全区域的数目。
接下来共N 组描述,分别对应每个区域,首先输入一个空行,接下来第一个数num 表示该区域顶点数,接下来共num 个整数对按逆时针方向描述每个顶点。
在描述起点终点前输入空行,然后两个整数S 和T 描述起点和终点。起点为之前读入的总第S 个顶点,终点同理。
输出
一行共一个数表示最短长度,保留4 位小数。

样例输入
2
4
0 0
1 0
1 1
0 1
4
2 2
3 2
3 3
2 3
1 7
样例输出
4.8284
提示
【数据规模和约定】

M 表示顶点总数

对于10%的数据,N=1。

对于30%的数据,N<=2。

对于50%的数据,N<=10,M<=50。

对于100%的数据,N<=100,M<=300,-32768<=读入的坐标<=32767。

题解
飞机肯定是一个顶点飞向另一个顶点,连边,判断是否经过凸包内部(用向量叉积),跑最短路。复杂度M^3

代码

#include
#define pa pair
#define inf 10000000
using namespace std;
inline int read() 
{ 
    int x=0,f=1;char ch=getchar(); 
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 
    return x*f; 
} 
double dis[305],f[305][305];
int n,cnt,num[105],S,T,sum[105];
struct node{int x,y,id;}a[305];
bool vis[305];
double Dis(node a,node b)
{
    return sqrt((double)(a.x-b.x)*(a.x-b.x)+(double)(a.y-b.y)*(a.y-b.y));
}
double Product(node a,node b)
{
    return (double)a.x*b.y-(double)b.x*a.y;
}
bool pd(node p1,node p2,node q1,node q2)
{
    if (p1.x==q1.x&&p1.y==q1.y) return 0;
    if (p2.x==q2.x&&p2.y==q2.y) return 0;
    if (p1.x==q2.x&&p1.y==q2.y) return 0;
    if (p2.x==q1.x&&p2.y==q1.y) return 0;
    node a[4],b[4];
    a[0].x=p1.x-q1.x;a[0].y=p1.y-q1.y;
    b[0].x=q2.x-q1.x;b[0].y=q2.y-q1.y;
    a[1]=b[0];
    b[1].x=p2.x-q1.x;b[1].y=p2.y-q1.y;
    a[2].x=q1.x-p1.x;a[2].y=q1.y-p1.y;
    b[2].x=p2.x-p1.x;b[2].y=p2.y-p1.y;
    a[3]=b[2];
    b[3].x=q2.x-p1.x;b[3].y=q2.y-p1.y;
    if (Product(a[0],b[0])*Product(a[1],b[1])>=0&&Product(a[2],b[2])*Product(a[3],b[3])>=0)
        return 1;
    return 0;
}
bool check(node x,node y)
{
    int p=0;
    for (int i=1;i<=cnt;i+=num[p])
    {
        p++;
        for (int j=i;jint k;
            if (j==i+num[p]-1) k=i;
            else k=j+1;
            if (pd(x,y,a[j],a[k]))
                return 0;
        }

    }
    return 1;
}
void dijkstra()
{
    priority_queuevector,greater >q;
    for (int i=1;i<=cnt;i++) dis[i]=inf;
    dis[S]=0;q.push(make_pair(0,S));
    while (!q.empty())
    {
        int now=q.top().second;q.pop();
        if (vis[now]) continue;vis[now]=1;
        for (int i=1;i<=cnt;i++)
        {
            if (f[now][i]==0) continue;
            if (dis[i]>dis[now]+f[now][i])
            {
                dis[i]=dis[now]+f[now][i];
                q.push(make_pair(dis[i],i));
            }
        }
    }
}
int main()
{
    n=read();
    for (int i=1;i<=n;i++)
    {
        num[i]=read();sum[i]=sum[i-1]+num[i];
        for (int j=1;j<=num[i];j++)
            a[++cnt].x=read(),a[cnt].y=read(),a[cnt].id=i;
    }
    for (int i=1;ifor (int j=i+1;j<=cnt;j++)
            if ((check(a[i],a[j])&&a[i].id!=a[j].id)||((j==i+1||(i==sum[a[i].id-1]+1&&j==sum[a[j].id]))&&a[i].id==a[j].id))
            {
                double dis=Dis(a[i],a[j]);
                f[i][j]=f[j][i]=dis;
            }
    S=read();T=read();
    dijkstra();
    printf("%.4lf",dis[T]);
    return 0;
}

你可能感兴趣的:(dijkstra,数论)