zoukankan      html  css  js  c++  java
  • 洛谷P1027题解

    首先,让我骂一句那没事找事的Car
    还取一个那么奇怪的名字
    看到这个题,恕我直言,我们明显可以看出这是一道图的最短路问题。由于这个题的数据范围很小(s只有100),所以在这里我们选取时间复杂度为O(n^3)的Floyd主要是好写
    相信大家都想得到这些,其实这道题最大的难点在预处理所以我刚才说了一大堆废话,针对他给出的每个城市,我们应该如何处理呢?
    首先是读入
     1 int a,b;
     2  scanf("%d%d%d%d",&n,&tf,&a,&b);
     3  for(int i=1;i<=4*n;i++)
     4    for(int j=1;j<=4*n;j++)
     5       e[i][j]=inf;
     6   for(int i=1;i<=n;i++)
     7   {
     8    for(int j=1;j<=6;j++)
     9      scanf("%d",wz[i]+j);
    10    for(int j=1;j<=5;j+=2)
    11    {
    12     wz[i][7]+=wz[i][j];
    13     wz[i][8]+=wz[i][j+1];
    14    }
    15  scanf("%d",wz[i]+9);

    这里用了一个wz[][]数组,wz[i][j](j=1,3,5,7)表示第i座城市的四个点的横坐标,wz[i][j](j=2,4,6,8)表示第i座城市的四个点的纵坐标,而j=9则是路费。其中wz[i][7]与wz[i][8]是要去计算的。

    而怎么算呢?我们可以得到一个公式xd=xa+xb-xc。 (y类似)(我们可以知道,已知的三点肯定是一个直角三角形,而(xa,ya)是TA的直角顶点,(xd,yd)便是TA所对的点。公式证明留给读者去思考。提示:利用两对角线交点是中点,然后使用中点坐标公式。)但我们还需要知道谁是直角顶点,这里很明显可以利用勾股定理求解。(当然还可以使用斜率乘积等于-1,但作者血与泪的教训还是建议你不要尝试。也可能是我太菜了
    计算代码
     1 double tp[3];
     2 int tp2=inf,tp3;
     3 tp[0]=dist1(wz[i][4],wz[i][6],wz[i][3],wz[i][5]);
     4 tp[1]=dist1(wz[i][2],wz[i][6],wz[i][1],wz[i][5]);
     5 tp[2]=dist1(wz[i][2],wz[i][4],wz[i][1],wz[i][3]);
     6 if(tp[0]+tp[1]==tp[2]){//我在之前把wz[i][7]处理成wz[i][1,3,5]的和,
     7 //这里直接减两倍横纵坐标
     8  wz[i][7]-=2*wz[i][5];wz[i][8]-=2*wz[i][6];
     9 }
    10 else if(tp[1]+tp[2]==tp[0]){
    11  wz[i][7]-=2*wz[i][1];wz[i][8]-=2*wz[i][2];
    12 }
    13 else if(tp[0]+tp[2]==tp[1]){
    14  wz[i][7]-=2*wz[i][3];wz[i][8]-=2*wz[i][4];
    15 }
    16 }

    这是dis1函数

    double dist(int a,int b,int c,int d){
     return sqrt((a-b)*(a-b)*1.0+1.0*(c-d)*(c-d));
    }

    然后枚举构造某城市之间飞机场的边。(这里我把城市里的每个顶点当一个点)

     1 for(int i=1;i<=n;i++)
     2 {
     3  for(int j=1;j<=4;j++)
     4    for(int k=j;k<=4;k++)
     5   {
     6    int u=(i-1)*4+j,v=(i-1)*4+k;//记得减一
     7    double dis=dist(wz[i][j*2-1],wz[i][k*2-1],wz[i][j*2],wz[i][k*2]);
     8    e[u][v]=e[v][u]=dis*wz[i][9];
     9   }
    10 }

    dist函数(与dist1的唯一区别就是开了根号)

    1 double dist(int a,int b,int c,int d){
    2  return sqrt((a-b)*(a-b)*1.0+1.0*(c-d)*(c-d));
    3 }

    接下来便是城市间最短距离的代码

     1 for(int i=1;i<=n;i++)
     2   for(int j=1;j<=n;j++)
     3     if(i!=j){//关键!!!作者调了一小时(┬_┬)
     4    for(int k=1;k<=4;k++)
     5      for(int l=1;l<=4;l++)
     6        {
     7         int u=(i-1)*4+k,v=(j-1)*4+l;
     8    double dis=dist(wz[i][k*2-1],wz[j][l*2-1],wz[i][k*2],wz[j][l*2]);
     9    e[u][v]=dis*tf;
    10     }
    11   }

    然后便是我们期待已久的Floyd

    for(int k=1;k<=n*4;k++)
      for(int i=1;i<=n*k;i++)
        for(int j=1;j<=n*4;j++)
          if(e[i][j]>e[i][k]+e[k][j])
              e[i][j]=e[i][k]+e[k][j];

    最后枚举起点终点,找到最短路

    1 ouble ans=inf;
    2   for(int i=(a-1)*4+1;i<=a*4;i++)
    3     for(int j=(b-1)*4+1;j<=b*4;j++)
    4       ans=min(ans,e[i][j]);
    5   printf("%.1lf",ans);

    是不是很简单?

    害我调了半天,万恶的Car
    最后给出完整代码
     
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=100005,maxm=500005,inf=0x3f3f3f3f;
     4 double e[1005][1005];
     5 int wz[1005][11];
     6 int n,tf;
     7 double dist(int a,int b,int c,int d){
     8  return sqrt((a-b)*(a-b)*1.0+1.0*(c-d)*(c-d));
     9 }
    10 double dist1(int a,int b,int c,int d){
    11  return (a-b)*(a-b)*1.0+1.0*(c-d)*(c-d);
    12 }
    13 int main()
    14 {
    15  int t;
    16  cin>>t;
    17  while(t--)
    18  {
    19   int a,b;
    20   scanf("%d%d%d%d",&n,&tf,&a,&b);
    21   for(int i=1;i<=4*n;i++)
    22     for(int j=1;j<=4*n;j++)
    23       e[i][j]=inf;
    24   for(int i=1;i<=n;i++)
    25   {
    26    for(int j=1;j<=6;j++)
    27      scanf("%d",wz[i]+j);
    28    for(int j=1;j<=5;j+=2)
    29    {
    30     wz[i][7]+=wz[i][j];
    31     wz[i][8]+=wz[i][j+1];
    32    }
    33    scanf("%d",wz[i]+9);
    34    double tp[3];
    35    int tp2=inf,tp3;
    36    tp[0]=dist1(wz[i][4],wz[i][6],wz[i][3],wz[i][5]);
    37    tp[1]=dist1(wz[i][2],wz[i][6],wz[i][1],wz[i][5]);
    38    tp[2]=dist1(wz[i][2],wz[i][4],wz[i][1],wz[i][3]);
    39    if(tp[0]+tp[1]==tp[2]){
    40     wz[i][7]-=2*wz[i][5];wz[i][8]-=2*wz[i][6];
    41    }
    42    else if(tp[1]+tp[2]==tp[0]){
    43     wz[i][7]-=2*wz[i][1];wz[i][8]-=2*wz[i][2];
    44    }
    45    else if(tp[0]+tp[2]==tp[1]){
    46     wz[i][7]-=2*wz[i][3];wz[i][8]-=2*wz[i][4];
    47    }
    48   }
    49   for(int i=1;i<=n;i++)
    50   {
    51    for(int j=1;j<=4;j++)
    52      for(int k=j;k<=4;k++)
    53     {
    54      int u=(i-1)*4+j,v=(i-1)*4+k;
    55      double dis=dist(wz[i][j*2-1],wz[i][k*2-1],wz[i][j*2],wz[i][k*2]);
    56      e[u][v]=e[v][u]=dis*wz[i][9];
    57     }
    58   }
    59   for(int i=1;i<=n;i++)
    60     for(int j=1;j<=n;j++)
    61       if(i!=j){
    62      for(int k=1;k<=4;k++)
    63        for(int l=1;l<=4;l++)
    64          {
    65           int u=(i-1)*4+k,v=(j-1)*4+l;
    66      double dis=dist(wz[i][k*2-1],wz[j][l*2-1],wz[i][k*2],wz[j][l*2]);
    67      e[u][v]=dis*tf;
    68       }
    69     }
    70   for(int k=1;k<=n*4;k++)
    71     for(int i=1;i<=n*k;i++)
    72       for(int j=1;j<=n*4;j++)
    73         if(e[i][j]>e[i][k]+e[k][j])
    74             e[i][j]=e[i][k]+e[k][j];
    75   double ans=inf;
    76   for(int i=(a-1)*4+1;i<=a*4;i++)
    77     for(int j=(b-1)*4+1;j<=b*4;j++)
    78       ans=min(ans,e[i][j]);
    79   printf("%.1lf",ans);
    80  }
    81  return 0;
    82 }
  • 相关阅读:
    yii源码五
    yii源码四
    yii源码三 -- db
    yii源码二 -- interfaces
    yii源码一 -- CComponent
    jquery效果 窗口弹出案例
    JS滚动条
    JS表单验证
    [TCP/IP] TCP流和UDP数据报之间的区别
    [TCP/IP] 关闭连接后为什么客户端最后还要等待2MSL
  • 原文地址:https://www.cnblogs.com/gxm123/p/12421234.html
Copyright © 2011-2022 走看看