1. 程式人生 > 實用技巧 >TYVJ1935 導彈防禦塔

TYVJ1935 導彈防禦塔

題面

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;
}