这里有一个不太优秀但是很好打的做法。
先说时间复杂度:\(O(15*n^2)\)。如果想看更优时间复杂度,请移步木示木干的博客。
AtCoder
题目大意:
\(N\) 个人,每个人有五个能力值 \(A_i,B_i,C_i,D_i,E_i\),我们要从中选出三个人成为一个组,一个组中一种能力的能力值定义为所有人该种能力的最大值,一个组的能力值定义为该组五种能力值的最小值。
选出一个组使得其能力值最大并输出之。
\(3\le N \le 3000, 1\le A_i,B_i,C_i,D_i,E_i\le 10^9\)。
由于有五种能力,三个人,我们考虑谁可以成为这个团队各个能力的顶梁柱,对该能力有贡献,也就是该种能力的最大值。
根据鸽巢原理,至少其中一个人对于该组的贡献至多有一种能力,而其余能力由另外两人贡献。所以我们就直接枚举两个人,再枚举另一个人对改组贡献的能力是哪一种,选择最大的即可。
当然,这样的实现方式有很多,我选择了最好写的排序找最大值。
注意在找最大值的时候不要与前面的人重复了。
考场代码确实比较丑,见谅。
//12252024832524 #include <cstdio> #include <cstring> #include <algorithm> #define TT template<typename T> using namespace std; typedef long long LL; const int MAXN = 3005; const LL INF = (1ll << 60); int n,now; LL ans; LL Read() { LL x = 0,f = 1;char c = getchar(); while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();} return x * f; } TT void Put1(T x) { if(x > 9) Put1(x/10); putchar(x%10^48); } TT void Put(T x,char c = -1) { if(x < 0) putchar('-'),x = -x; Put1(x); if(c >= 0) putchar(c); } TT T Max(T x,T y){return x > y ? x : y;} TT T Min(T x,T y){return x < y ? x : y;} TT T Abs(T x){return x < 0 ? -x : x;} struct node { LL a[5],ID; }s[6][MAXN]; bool cmp(node x,node y) { return x.a[now] > y.a[now]; } void update(node A,node B,node C) { LL ret = INF; for(int i = 0;i < 5;++ i) ret = Min(ret,Max(A.a[i],Max(B.a[i],C.a[i]))); ans = Max(ans,ret); } int main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); n = Read(); for(int i = 1;i <= n;++ i) for(int j = 0;j < 5;++ j) { s[0][i].a[j] = Read(); s[0][i].ID = i; for(int k = 1;k < 6;++ k) s[k][i].a[j] = s[0][i].a[j],s[k][i].ID = i; } for(now = 0;now < 5;++ now) sort(s[now]+1,s[now]+n+1,cmp); for(int i = 1;i <= n;++ i) for(int j = i+1;j <= n;++ j) for(int k = 0;k < 5;++ k) for(int l = 1;l <= 3;++ l) { if(s[k][l].ID != i && s[k][l].ID != j)//不要重复了 update(s[5][i],s[5][j],s[k][l]); } Put(ans); return 0; }