10.23T2 二分+二分图(滑稽)
#3847 轰炸
描述
Ljr 家里有矿。
Ljr 有 M 套房子,你可以把它们分别看成 M 个点分布在直角坐标系中,Jerryzhong 非常 痛恨 ljr 这个青春富豪,于是他想要炸掉 ljr 的这 M 套房子。
Jerryzhong 通过红石科技造了 N 台红石大炮,由于客户端不兼容,因此这 N 台大炮随 机分布在了这个直角坐标系中,每一台红石大炮的炮弹需要 t1 分钟发射,发射一枚炮弹之 后需要 t2 分钟重新装弹,炮弹飞行的速度为 v/分钟,他想知道最少需要多少时间才能轰炸 完 ljr 的 M 套房子,由于 Jerryzhong 忙着做(shui)题(tie),因此他将这件事情拜托给了你,你 能回答这个问题吗?
你可以认为 N 台大炮一开始都已经填装好了弹药,且炮台和房子的距离为欧几里得距 离,所有炮弹无视地形限制,水平飞行,Jerryzhong 可以同时使用多个炮台,但每个炮台一 次只能发射一枚炮弹,炸掉房子不需要时间。
由于 ljr 是个阔佬,所以他能够重新买 Q-1 次房,因此 Jerryzhong 会向你询问 Q 次炸完 房子的最少时间。
输入
第一行一个数 Q 表示询问次数。
接下来一行 5 个整数 N,M,t1,t2,v 意义如题所述。
接下来 N 行,每行两个数 x,y,表示 N 台红石炮的坐标。
接下来 M 行,每行两个整数 x,y,表示 ljr 的 M 套房子的坐标。
输出
共 Q 行,每行一个实数表示最少时间,精确到小数点后 6 位。
提示
numQ N M 其他
1 =1 ≤3 ≤2 无
2 =1 ≤6 ≤5 无
3 =1 ≤10 ≤10 v=1
4 =1 ≤10 ≤10 t2=0
5 =1 ≤10 ≤10 t1=0
6 ≤5 ≤50 ≤50 t1=0,t2=0
7 ≤5 ≤50 ≤50 v=1
8 ≤10 ≤50 ≤50 无
9 ≤15 ≤50 ≤50 无
10 ≤15 ≤50 ≤50 无
标签
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<iomanip> 6 #include<algorithm> 7 #define N 105 8 using namespace std; 9 long long n,m; 10 double v,t2,t1; 11 double eps=1e-9; 12 long long matching[N],vis[N],g[10005][100],paox[N],paoy[N],fangx[N],fangy[N]; 13 double dis[20000][100],Tim[125005]; 14 int tot; 15 bool match(long long u) { 16 for(long long i=1; i<=m; i++) { 17 if(vis[i]||!g[u][i])continue; 18 vis[i]=1; 19 if(!matching[i]||match(matching[i])) { 20 matching[i]=u; 21 return true; 22 } 23 } 24 return false; 25 } 26 long long hun() { 27 long long ans=0; 28 for(long long i=1; i<=n*m; i++) { 29 memset(vis,0,sizeof vis); 30 if(match(i))ans++; 31 } 32 return ans; 33 } 34 double sq(double x) { 35 return x*x; 36 } 37 double getdis(long long i,long long j) { 38 return sqrt(sq(paox[i]-fangx[j])+sq(paoy[i]-fangy[j])); 39 } 40 bool check(double mid) { 41 memset(g,0,sizeof g); 42 for(long long i=1; i<=m; i++) { //拆点 43 for(long long j=1; j<=n; j++) { // 44 for(long long k=1; k<=m; k++) { 45 if(dis[(j-1)*m+i][k]-eps<=mid) { 46 g[(j-1)*m+i][k]=1; 47 } 48 } 49 } 50 } 51 if(hun()==m)return true; 52 return false; 53 } 54 int main() { 55 long long Q; 56 cin>>Q; 57 while(Q--) { 58 tot=0; 59 cin>>n>>m>>t1>>t2>>v; 60 for(long long i=1; i<=n; i++)cin>>paox[i]>>paoy[i]; 61 for(long long i=1; i<=m; i++)cin>>fangx[i]>>fangy[i]; 62 63 double ans; 64 for(long long i=1; i<=m; i++) { //拆点 65 for(long long j=1; j<=n; j++) { // 66 for(long long k=1; k<=m; k++) { 67 dis[(j-1)*m+i][k]=getdis(j,k)/v+(t2+t1)*i-t2; 68 Tim[++tot]=dis[(j-1)*m+i][k]; 69 } 70 } 71 } 72 sort(Tim+1,Tim+1+tot);int l=1,r=tot; 73 // for(int i=1;i<=tot;i++)cout<<Tim[i]<<" ";cout<<"\n"; 74 // cout<<check(Tim[6])<<" sss\n"; 75 // for(int i=1;i<=tot;i++){ 76 // memset(matching,0,sizeof matching); 77 // cout<<"i="<<i<<" Check="<<check(Tim[i])<<"\n"; 78 // } 79 while(l<=r) { 80 memset(matching,0,sizeof matching); 81 int mid=(l+r)/2; 82 if(check(Tim[mid]))r=mid-1,ans=Tim[mid]; 83 else l=mid+1; 84 } 85 cout<<fixed<<setprecision(6)<<ans<<'\n'; 86 } 87 return 0; 88 }
over