題解:AT_abc257_d [ABC257D] Jumping Takahashi 2

0x3f3f3f3f3f3f發表於2024-09-01

[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。

題解結束了,有問題大家可以私信我。

相關文章