CF1619D. New Year's Problem
大致題意
Vlad要給 \(n\) 個朋友買禮物,有 \(m\) 個商店。定義 \(p_{ij}\) 為從第 \(i\) 個商店給第 \(j\) 個朋友買禮物產生的快樂值(由矩陣給出)。定義 \(α\) 為所有朋友的快樂值的最小值。Vlad最多訪問 \(n-1\) 個商店,給每一位朋友買一樣禮物,問 \(α\) 值最大是多少。
解題思路(二分)
遇到這種求最小值最大的題,很快就可以想到使用二分解決。這道題的關鍵在於考慮判斷能否實現的check函數怎么實現。
在check函數中,如果當前值 \(x\) 想要可成立,需要滿足兩個條件
① 所有的朋友都至少有一個商店能買到快樂值大於等於 \(x\) 的禮物
② 最多只訪問 \(n-1\) 個商店
第一個要求我們可以很方便的實現,只需要開一個大小為 \(n\) 的數組,遍歷統計這個朋友能否成功買到合適禮物。
對於第二個要求,我們可以轉化,為一個商店是否能過同時滿足大於兩個人的要求,如果可以,說明最多只用訪問 \(n-1\) 個商店。
原因如下,如果每一個朋友都有一個對應的商店可以買到對應合適禮物,此時需要訪問 \(n\) 個商店。此時還有一個商店能買到兩個人的禮物,那么這兩個人可以都去這個商店買,那么需要的總商店數變為 \(n-1\) 個商店。
這樣我們就可以實現check函數,用二分完成要求。
解題思路(排序)
賽后在看大佬代碼的時候看到了一種不一樣的代碼
Submission #140035383 - Codeforces
int ans = 0;
for (int j = 0; j < m; j++){
vector<int> p2 = p[j];
sort(p2.begin(), p2.end(), greater<int>());
ans = max(ans, p2[1]);
}
for (int j = 0; j < n; j++){
int mx = 0;
for (int k = 0; k < m; k++){
mx = max(mx, p[k][j]);
}
ans = min(ans, mx);
}
不用二分,非常簡短的做出了這題。
稍微的研究了一下,說一下自己的理解
這種做法的核心思想與二分的check函數類似。可以概括為一句話:滿足所有人都被選到的同時,讓一個商店滿足兩個人。
前面的一重循環+排序,作用就是找出,如果要讓一個商店滿足兩個人,那么最大能給出的快樂值是多少。(而且這個值是最優的)
循環結束后,得到的 \(ans\) 中,儲存的是取了兩個人的商店,他對於答案的貢獻。
后面的循環就比較簡單,就是找出對於一個人,禮物最大的快樂值。
將這些值去min,就得到了最終答案。
代碼(二分)
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
vector<int> sp[maxn + 10];
int n, m;
bool check(int x)
{
vector<bool> f(n + 10);
bool ff = false;
for (int i = 1; i <= m; i++) {
int cnt = 0;
for (int j = 1; j <= n; j++) {
if (sp[i][j] >= x) {
cnt++;
f[j] = 1;
}
}
if (cnt >= 2)
ff = true;
}
if (!ff)
return false;
for (int i = 1; i <= n; i++) {
if (!f[i])
return false;
}
return true;
}
void solve()
{
cin >> m >> n;
int mx = 0;
for (int i = 1; i <= m; i++) {
sp[i].clear();
sp[i].emplace_back(0);
for (int j = 1; j <= n; j++) {
int t;
cin >> t;
sp[i].emplace_back(t);
mx = max(t, mx);
}
}
int l = 0, r = mx;
int ans = 0;
while (l <= r) {
int mid = (l + r) / 2;
if (check(mid)) {
ans = mid;
l = mid + 1;
}
else
r = mid - 1;
}
cout << ans << "\n";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}