1 条题解

  • 0
    @ 2025-5-4 16:31:13

    分析:

    该代码结合了二分图最大匹配算法(匈牙利算法)和枚举算法。匈牙利算法用于解决二分图的最大匹配问题,枚举算法则用于枚举边的组合,以找出满足条件的最小差值。

    解题思路

    本题的目标是在给定机场、信号塔和飞机信息的情况下,找到满足特定条件(至少有 d - 1 对信号塔 - 飞机匹配)的边的最小权值差。解题思路是先计算所有信号塔和飞机之间边的权值,对边按权值排序,然后通过枚举边的组合,使用匈牙利算法进行二分图匹配,找到满足条件的最小权值差。

    解题原理

    1.边权值计算:对于每个信号塔和每架飞机,计算飞机从对应机场到该信号塔所需的时间,作为边的权值。

    2.二分图匹配:使用匈牙利算法进行二分图匹配。在 dfs 函数中,尝试为一个信号塔寻找一个未匹配的飞机,若该飞机已匹配,则尝试为其原来的匹配对象寻找新的匹配。

    3.枚举边组合:通过枚举边的起始和结束位置,不断尝试找到满足至少有 d - 1 对匹配的边的组合,并计算这些组合中边权值的最小差值。

    实现步骤

    1.输入处理:读取机场数量 n、信号塔数量 k、飞机数量 p 和所需匹配对数 d,以及机场、信号塔和飞机的相关信息。

    2.可行性判断:若 d 大于信号塔和飞机数量的最小值,输出 Impossible!;若 d 小于等于 1,输出 0:0。

    3.边权值计算:计算所有信号塔和飞机之间边的权值,并存储在 edges 数组中。

    4.边排序:对 edges 数组按边权值从小到大排序。

    5.枚举边组合并匹配:调用 kk 函数,枚举边的组合,使用匈牙利算法进行二分图匹配,找到满足条件的最小权值差。

    6.输出结果:若找到满足条件的最小权值差,将其转换为分钟和秒的格式输出;否则,输出 Impossible!。

    c++代码:

    #include<iostream>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<stdio.h>
    #include<cstring>
    using namespace std;
    double ans;
    int n,k,p,d,cnt,adj[51][91],num[51],to[150];
    bool visit[51];
    struct edge
    {
       int id1,id2;
       double w;
       bool operator <(const edge &temp)const
       {
            return w<temp.w;
       }
    };
    edge edges[5000];
    struct airport
    {
        double x,y;
    };
    airport airports[60];
    struct tower
    {
        double x,y;
    };
    tower towers[60];
    struct plane
    {
        double h,m,s;
        int f,t;
    };
    plane planes[100];
    double dist(double x1,double y1,double x2,double y2)
    {
           return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
    }
    bool dfs(int id)
    {
         int i,j,s,q,ip; 
         for(i=0;i<num[id];i++)
         {
            ip=adj[id][i];
            if(to[ip]==ip)
            {
                to[id]=ip;
                to[ip]=id;
                return true;
            }
            else
            {
                if(!visit[to[ip]])
                {
                   visit[to[ip]]=true;
                   if(dfs(to[ip]))
                   {
                      to[id]=ip;
                      to[ip]=id;
                      return true;
                   }
                }
            }
         }
         return false;
    }
    double kk()
    {
           int i,j,s,q,temp;
           double res=1000000000;
           for(i=0;i<cnt;i++)
           {
              for(j=0;j<k;j++) 
                 num[j]=visit[j]=0;
              for(j=0;j<k+p;j++) 
                 to[j]=j;
              temp=0;
              for(j=i+1;j<cnt;j++)
              {
                  int id1=edges[j].id1,id2=edges[j].id2;
                  if(id1==edges[i].id1||id2==edges[i].id2)
                      continue;
                  adj[id1][num[id1]++]=id2;
                  visit[id1]=true;
                  temp+=dfs(id1); 
                  if(temp>=d-1) 
                     break;
              }
              if(j<cnt)
              {
                 if(res>edges[j].w-edges[i].w)
                    res=edges[j].w-edges[i].w;
              }
              else
                 break;
           }
           return res;
    }
    int main()
    {
        int i,j,s,q,id;
        while(scanf("%d%d%d%d",&n,&k,&p,&d)&&n+k+p+d)
        {
              for(i=0;i<n;i++)
                scanf("%lf%lf",&airports[i].x,&airports[i].y);
              for(i=0;i<k;i++)           
                scanf("%lf%lf",&towers[i].x,&towers[i].y);
               for(i=0;i<p;i++)
               {
                  scanf("%lf%lf%d%d%lf",&planes[i].h,&planes[i].m,&planes[i].f,&planes[i].t,&planes[i].s);                          
                  planes[i].f--;
               }
               if(d>min(k,p))
               { 
                    puts("Impossible!");
                    continue;
               }
               if(d<=1)
               {
                  printf("0:0\n");
                  continue;
               }
               cnt=0;
               for(i=0;i<k;i++)
                 for(j=0;j<p;j++)
                 {
                    edges[cnt].id1=i;
                    edges[cnt].id2=j+k;
                    id=planes[j].f;
                    edges[cnt].w=dist(airports[id].x,airports[id].y,towers[i].x,towers[i].y)/planes[j].s;
                    edges[cnt].w+=(planes[j].h*60.00+planes[j].m)*60.00;
                    edges[cnt].w/=60.00;
                    cnt++;
                 }
              sort(edges,edges+cnt);
              ans=kk();
              if(ans<1000000000)
                printf("%d:%d\n",((int)(ans+0.5))/60,((int)(ans+0.5))%60);
              else
                puts("Impossible!");
        }
        return 0;
    }
    • 1

    信息

    ID
    535
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    4
    已通过
    1
    上传者