列表

详情


NC51274. 导弹防御塔

描述

Freda的城堡——
“Freda,城堡外发现了一些入侵者!”
“喵...刚刚探究完了城堡建设的方案数,我要歇一会儿嘛lala~”
“可是入侵者已经接近城堡了呀!”
“别担心,rainbow,你看呢,这是我刚设计的导弹防御系统的说~”
“喂...别卖萌啊……”
Freda控制着N座可以发射导弹的防御塔。每座塔都有足够数量的导弹,但是每座塔每次只能发射一枚。在发射导弹时,导弹需要T1秒才能从防御塔中射出,而在发射导弹后,发射这枚导弹的防御塔需要T2分钟来冷却。
所有导弹都有相同的匀速飞行速度V,并且会沿着距离最短的路径去打击目标。计算防御塔到目标的距离Distance时,你只需要计算水平距离,而忽略导弹飞行的高度。导弹在空中飞行的时间就是 (Distance/V) 分钟,导弹到达目标后可以立即将它击毁。
现在,给出N座导弹防御塔的坐标,M个入侵者的坐标,T1、T2和V,你需要求出至少要多少分钟才能击退所有的入侵者。

输入描述

第一行五个正整数N,M,T1,T2,V。
接下来M行每行两个整数,代表入侵者的坐标。
接下来N行每行两个整数,代表防御塔的坐标。

输出描述

输出一个实数,表示最少需要多少分钟才能击中所有的入侵者,四舍五入保留六位小数。

示例1

输入:

3 3 30 20 1
0 0
0 50
50 0
50 50
0 1000
1000 0

输出:

91.500000

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 102ms, 内存消耗: 864K, 提交时间: 2019-10-05 17:20:41

//Author:XuHt
#include <cmath>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#define pii pair<int, int>
#define x first
#define y second
using namespace std;
const int N = 56, M = 2506;
const double eps = 1e-8;
int n, m, t, t2, V, f[M];
double t1;
bool v[M];
pii a[N], b[N];
pair<int, double> c[M];
vector<int> e[N];

inline double S(pii a, pii b) {
	int dx = a.x - b.x, dy = a.y - b.y;
	return sqrt(dx * dx + dy * dy);
}

bool dfs(int x) {
	for (unsigned int i = 0; i < e[x].size(); i++) {
		int y = e[x][i];
		if (v[y]) continue;
		v[y] = 1;
		if (!f[y] || dfs(f[y])) {
			f[y] = x;
			return 1;
		}
	}
	return 0;
}

inline bool pd(double mid){
	memset(f, 0, sizeof(f));
	for (int i = 1; i <= m; i++) {
		e[i].clear();
		for (int j = 1; j <= t; j++)
			if (c[j].y + S(a[i], b[c[j].x]) / V <= mid)
				e[i].push_back(j);
	}
	for (int i = 1; i <= m; i++) {
		memset(v, 0, sizeof(v));
		if (!dfs(i)) return 0;
	}
	return 1;
}

int main() {
	cin >> n >> m >> t1 >> t2 >> V;
	t = n * m;
	t1 /= 60;
	for (int i = 1; i <= m; i++)
		scanf("%d %d", &a[i].x, &a[i].y);
	for (int i = 1; i <= n; i++)
		scanf("%d %d", &b[i].x, &b[i].y);
	for (int i = 1; i <= m; i++)
		for (int j = 1; j <= n; j++) {
			int k = (i - 1) * n + j;
			c[k].x = j;
			c[k].y = (i - 1) * (t1 + t2) + t1;
		}
	double l = t1, r = 100000;
	while (l + eps < r) {
		double mid = (l + r) / 2;
		if (pd(mid)) r = mid;
		else l = mid;
	}
	printf("%.6f\n", l);
	return 0;
}

C++ 解法, 执行用时: 118ms, 内存消耗: 1416K, 提交时间: 2022-04-11 16:44:15

#include<bits/stdc++.h>
#define ma match[i]
#define sq(v) (v)*(v)
using namespace std;
const int nm=51;
bitset<nm>c;
int n,m,num,Y[nm][2],match[nm][2];
double t[nm][nm][nm],mid;
bool dfs(int x,int y){
    for(int i=1;i<=m;i++)
        if(t[x][y][i]<=mid&&c[i]){
            c[i]=false;
            if(!ma[0]||dfs(ma[0],ma[1]))return ma[0]=x,ma[1]=y,true;
        }return false;
}
int main(){
    double t1,t2,v,ans;
    cin>>n>>m>>t1>>t2>>v;
    t1/=60,t2+=t1;
    for(int i=1;i<=m;i++)cin>>Y[i][0]>>Y[i][1];
    for(int i=1,x,y;i<=n;i++){
    	cin>>x>>y;
        for(int j=1;j<=m;j++){
            t[i][1][j]=t1+sqrt(sq(x-Y[j][0])+sq(y-Y[j][1]))/v;
            for(int k=2;k<=m;k++)t[i][k][j]=t[i][k-1][j]+t2;
        }
    }
	for(double l=0,r=1e7;r-l>1e-7;){
        memset(match,0,sizeof match);
        num=0,mid=(l+r)/2;
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)c.set(),num+=dfs(i,j);
        if(num==m)ans=r=mid;
        else l=mid;
    }
    printf("%.6lf",ans);
    return 0;
}

上一题