TYVJ1935 導彈防禦塔
阿新 • • 發佈:2020-09-21
題面
Freda的城堡遭受了 M 個入侵者的攻擊!
Freda控制著 N 座導彈防禦塔,每座塔都有足夠數量的導彈,但是每次只能發射一枚。
在發射導彈時,導彈需要 T1 秒才能從防禦塔中射出,而在發射導彈後,發射這枚導彈的防禦塔需要 T2 分鐘來冷卻。
所有導彈都有相同的勻速飛行速度 V,並且會沿著距離最短的路徑去打擊目標。
計算防禦塔到目標的距離Distance時,你只需要計算水平距離,而忽略導彈飛行的高度。
導彈在空中飛行的時間就是 (Distance/V) 分鐘,導彈到達目標後可以立即將它擊毀。
現在,給出 N 座導彈防禦塔的座標,M 個入侵者的座標,T1,T2 和 V。因為Freda的小夥伴Rainbow就要來拜訪城堡了,你需要求出至少多少分鐘才能擊退所有的入侵者。
輸入格式
第一行五個正整數N,M,T1,T2,V。
接下來 M 行每行兩個整數,代表入侵者的座標。
接下來 N 行每行兩個整數,代表防禦塔的座標。
輸出格式
輸出一個實數,表示最少需要多少分鐘才能擊中所有的入侵者,四捨五入保留六位小數。
資料範圍
1≤N,M≤50,座標絕對值不超過10000,T1,T2,V不超過2000。
輸入樣例:
3 3 30 20 1
0 0
0 50
50 0
50 50
0 1000
1000 0
輸出樣例:
91.500000
題解
多重匹配有四種解決方案
1.把點全部拆開
2,左邊點集只能連一次, 那就在匈牙利演算法的時候, 依次去匹配 右點 第 k 次連線, 都匹配滿, 再去依次重匹配 右點 的 k次連線
3.右點集只能連一次, 可以交換成2, 或者在匈牙利演算法的時候讓 左點 匹配 k次
4.網路流新增源點和匯點, 直接做
這題我們使用3的減緩做法, 讓敵人去匹配子彈
這道題是單調的, 二分時間
判斷在此時間內 每個炮塔能發射多少子彈(最多50, 多了沒用, 敵人就50個)
敵人和能打到他的子彈連邊, 匈牙利就完事
#include <bits/stdc++.h> #define all(n) (n).begin(), (n).end() #define se second #define fi first #define pb push_back #define mp make_pair #define sqr(n) (n)*(n) #define rep(i,a,b) for(int i=(a);i<=(b);++i) #define per(i,a,b) for(int i=(a);i>=(b);--i) #define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr) using namespace std; typedef unsigned long long ull; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> PII; typedef pair<ll, ll> PLL; typedef vector<int> VI; typedef double db; const int N = 50 + 5; int n, m, _, k; int match[N * N], c; db t1, t2, sp; PII a[N], b[N]; bool v[N * N]; double dis(int x, int y) { return sqr(a[x].fi - b[y].fi) + sqr(a[x].se - b[y].se); } bool dfs(int x, double mid) { per (i, n * c, 1) { if (dis(x, (i - 1) / c + 1) > sqr(sp) * sqr(mid - (i - 1) % c * (t1 + t2) - t1)) continue; if (v[i]) continue; v[i] = 1; if (!match[i] || dfs(match[i], mid)) { match[i] = x; return 1; } } return 0; } bool check(double mid) { c = (int)min((mid + t2) / (t1 + t2), 50.0); per (i, n * c, 1) match[i] = 0; rep (i, 1, m) { per (j, n * c, 1) v[j] = 0; if (!dfs(i, mid)) return 0; } return 1; } int main() { IOS; cin >> n >> m >> t1 >> t2 >> sp; t1 /= 60; rep (i, 1, m) cin >> a[i].fi >> a[i].se; rep (i, 1, n) cin >> b[i].fi >> b[i].se; double l = 0, r = 2e18; while (r - l >= 1e-8) { double mid = (l + r) / 2; if (check(mid)) r = mid; else l = mid; } cout << setiosflags(ios::fixed) << setprecision(6) << r; return 0; }