1 条题解
-
0
分析:
该代码结合了二分图最大匹配算法(匈牙利算法)和枚举算法。匈牙利算法用于解决二分图的最大匹配问题,枚举算法则用于枚举边的组合,以找出满足条件的最小差值。
解题思路
本题的目标是在给定机场、信号塔和飞机信息的情况下,找到满足特定条件(至少有 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
- 上传者