[ABC257D] Jumping Takahashi 2
部落格食用更佳:My blog。
大體思路
這題是一道二分題,因為 \(S\) 越大,就越容易滿足題目要求,\(S\) 越小,就越難滿足題目要求,符合二分的特點。
下面先貼上二分程式碼。
LL l = 0, r = 1e10;
while (l < r) {
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
cout << r;// 二分板子。
check 函式怎麼寫
因為這題 \(n\) 比較小,所以我們可以在每次 check 時,列舉起點,每次從那個點深搜一遍,然後判斷搜尋到的點數量是否為 \(n\),若搜到了 \(n\) 個點,直接返回 \(1\),若所有點都沒有搜到 \(n\) 個點,返回 \(0\)。
下面是 check 函式程式碼。
bool check(LL mid) {
for (LL i = 1; i <= n; i++) {
memset(vis, 0, sizeof vis);// vis 用來標記是否已訪問過。
cnt = 0;// 用來記錄訪問了幾個點,cnt 和 vis 陣列每次都要清空。
dfs(i, mid);// 搜尋。
if (cnt == n) return 1;
}
return 0;
}
dfs 函式怎麼寫
dfs 傳參要傳兩個引數:當前點和訓練次數。每次判斷每個點是否之前被訪問過,訪問過就結束掉,沒訪問過就把這個點標記為 \(1\),接著列舉下一個點,繼續搜尋。
下面就是程式碼。
void dfs(LL u, LL mid) {
if (vis[u]) return; // 檢視是否訪問過。
vis[u] = 1, cnt++;
for (LL v = 1; v <= n; v++) { // 列舉每個點。
if (p[u] * mid < abs(x[u] - x[v]) + abs(y[u] - y[v])) continue; // 到不了就 continue。
dfs(v, mid);
}
}
Code
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const LL N = 205;
LL n, x[N], y[N], p[N], cnt, vis[N];
void dfs(LL u, LL mid) {
if (vis[u]) return;
vis[u] = 1, cnt++;
for (LL v = 1; v <= n; v++) {
if (p[u] * mid < abs(x[u] - x[v]) + abs(y[u] - y[v])) continue;
dfs(v, mid);
}
}
bool check(LL mid) {
for (LL i = 1; i <= n; i++) {
memset(vis, 0, sizeof vis);
cnt = 0;
dfs(i, mid);
if (cnt == n) return 1;
}
return 0;
}
signed main() {
cin >> n;
for (LL i = 1; i <= n; i++) cin >> x[i] >> y[i] >> p[i];
LL l = 0, r = 1e10;
while (l < r) {
LL mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
cout << r;
return 0;
}
謹記
一定要開 long long。
題解結束了,有問題大家可以私信我。