题面

你想从

N

N

N 个候选人中选 3 个人。

每个人有五个属性

A

i

,

B

i

,

C

i

,

D

i

,

E

i

A_i,B_i,C_i,D_i,E_i

Ai​,Bi​,Ci​,Di​,Ei​。

一种选人方案假设选了三个人

x

,

y

,

z

x,y,z

x,y,z ,那么这个方案的力量Strength就是

min

{

max

{

A

x

,

A

y

,

A

z

}

max

{

B

x

,

B

y

,

B

z

}

max

{

C

x

,

C

y

,

C

z

}

max

{

D

x

,

D

y

,

D

z

}

max

{

E

x

,

E

y

,

E

z

}

}

\min\left\{\begin{matrix} \max\{A_x,A_y,A_z\}\\ \max\{B_x,B_y,B_z\}\\ \max\{C_x,C_y,C_z\}\\ \max\{D_x,D_y,D_z\}\\ \max\{E_x,E_y,E_z\} \end{matrix}\right\}

min⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧​max{Ax​,Ay​,Az​}max{Bx​,By​,Bz​}max{Cx​,Cy​,Cz​}max{Dx​,Dy​,Dz​}max{Ex​,Ey​,Ez​}​⎭⎪⎪⎪⎪⎬⎪⎪⎪⎪⎫​

力量Strength最大的方案的力量Strength是多少。

输入分别给出

N

N

N 和

N

N

N 行整数

A

i

,

B

i

,

C

i

,

D

i

,

E

i

A_i,B_i,C_i,D_i,E_i

Ai​,Bi​,Ci​,Di​,Ei​。

输出一行一个整数表示答案。

3

N

3000

,

1

A

i

,

B

i

,

C

i

,

D

i

,

E

i

1

0

9

3\leq N\leq 3000,1\leq A_i,B_i,C_i,D_i,E_i \leq 10^9

3≤N≤3000,1≤Ai​,Bi​,Ci​,Di​,Ei​≤109.

Sample Input

10
6 7 5 18 2
3 8 1 6 3
7 2 8 7 7
6 3 3 4 7
12 8 9 15 9
9 8 6 1 10
12 9 7 8 2
10 3 17 4 10
3 1 3 19 3
3 14 7 13 1

Sample output

10

题解

首先,我们会想到一种

N

3

N^3

N3 的暴力做法。

之所以这样过不了,是因为我们想知道的力量与每个属性都有关,又跟每个属性的最大值有关,属性不同的有

N

N

N 个人,因此时间复杂度便上天。

为了消除这些限制,同时发现这道题相当于求最小值前提下的最大值,于是我们不妨想想二分

我们二分一个答案,表示每项属性的最大值都要大于等于这个值。那么此时,相当于定了一个标准——一个属性大于等于这个值为合格,否则不合格。要求是要让选出的三个人中每项属性都至少有一个人合格。此时,由于我们想知道的是否合法每个属性的合格与否有关,而每个属性只有两种情况:合格/不合格,因此,把每项属性合格情况(一共

2

5

2^5

25 种)相同的合并到一起,我们相当于只有

2

5

=

32

2^5=32

25=32 位候选人了!然后再随便用一个三次方的暴力(时间

2

15

2^{15}

215)就可以解决问题,或者稍加dp优化变成平方,跑到最优解 6~8 ms。

时间复杂度

O

(

log

X

(

5

N

+

2

10

)

)

O(\log X(5N+2^{10}))

O(logX(5N+210))

CODE

#include<map>
#include<queue>
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 3005
#define ENDL putchar('\n')
#define LL long long
#define DB double
#define lowbit(x) ((-x) & (x))
LL read() {
LL f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f * x;
}
int n,m,i,j,s,o,k;
int a[MAXN][10];
bool dp[4][1<<5|5];
bool check(int val) {
memset(dp,0,sizeof(dp));
for(int i = 1;i <= n;i ++) {
int S = 0;
for(int j = 1;j <= 5;j ++) {
if(a[i][j] >= val) S |= (1<<(j-1));
}
dp[1][S] = 1;
}
dp[1][0] = dp[2][0] = dp[3][0] = 1;
for(int kk = 1;kk <= 2;kk ++) {
for(int i = 0;i < (1<<5);i ++) {
if(dp[kk][i])
for(int j = 0;j < (1<<5);j ++) {
dp[kk+1][i|j] |= dp[1][j];
}
}
}
return dp[3][(1<<5)-1];
}
int main() {
n = read();
for(int i = 1;i <= n;i ++) {
for(int j = 1;j <= 5;j ++) {
a[i][j] = read();
}
}
int ans = 0;
for(int i = 30;i >= 0;i --) {
if(ans+(1<<i) <= 1000000000 && check(ans+(1<<i))) ans += (1<<i);
}
printf("%d\n",ans);
return 0;
}

别的做法

暴力

有一个

15

N

2

15*N^2

15∗N2 的做法,详见PPL的博客
其核心思想在于:最后的方案中,不可能三个人都贡献了

2

\geq2

≥2 个最大值,因此一定有一个人贡献了

1

\leq 1

≤1 个最大值,那么不妨就令这个人为这个属性中可以选的最大的一个人,于是暴力可以少一维。

Dynamic Programming

官方题解中的第二种做法。

题意可以转化为:你先选三个候选人

x

,

y

,

z

x,y,z

x,y,z,然后每个属性你都在三个人中选一个人的拿出来,要让这五个数的最小值最大。不难发现这样和原题面(贪心地选最大的)最终答案是一样的。

那么就可以设计出一个 DP:

d

p

[

i

]

[

j

]

[

k

]

dp[i][j][k]

dp[i][j][k] 表示前

i

i

i 个人中选了

j

j

j 个人(

j

3

j\leq3

j≤3) ,属性状态为

k

k

k(

k

2

5

k\leq 2^5

k≤25) 时的最大答案(

k

k

k 的二进制第

i

i

i 位表示第

i

i

i 种属性是否已经选了人),转移的时候保证每种属性只选一个人。转移可以

O

(

5

)

O(5)

O(5) 。

那么总时间就是

O

(

15

N

2

5

)

O(15N*2^5)

O(15N∗25)。

官方代码

Atcoder ZONe Energy Programming Contest C - MAD TEAM(二分)的更多相关文章

  1. AtCoder SoundHound Inc. Programming Contest 2018 E + Graph (soundhound2018_summer_qual_e)

    原文链接https://www.cnblogs.com/zhouzhendong/p/AtCoder-SoundHound-Inc-Programming-Contest-2018-E.html 题目 ...

  2. AtCoder diverta 2019 Programming Contest 2

    AtCoder diverta 2019 Programming Contest 2 看起来我也不知道是一个啥比赛. 然后就写写题解QWQ. A - Ball Distribution 有\(n\)个 ...

  3. 【AtCoder】M-SOLUTIONS Programming Contest

    M-SOLUTIONS Programming Contest A - Sum of Interior Angles #include <bits/stdc++.h> #define fi ...

  4. 【AtCoder】AISing Programming Contest 2019

    本来以为是1199rated的..仔细一看发现是1999,所以就做了一下 这场涨分很轻松啊...为啥又没打 等pkuwc考完我一定打一场atcoder(咕咕咕,咕咕咕,咕咕咕咕咕咕咕~) 但是其实我思 ...

  5. 【AtCoder】Yahoo Programming Contest 2019

    A - Anti-Adjacency K <= (N + 1) / 2 #include <bits/stdc++.h> #define fi first #define se se ...

  6. 【AtCoder】KEYENCE Programming Contest 2019

    A - Beginning 这个年份恐怕需要+2 #include <bits/stdc++.h> #define fi first #define se second #define p ...

  7. 【AtCoder】Dwango Programming Contest V题解

    A - Thumbnail 题意简述:给出N个数,找出N个数中和这N个数平均值绝对值最小的数 根据题意写代码即可= = #include <bits/stdc++.h> #define f ...

  8. zoj The 12th Zhejiang Provincial Collegiate Programming Contest Team Formation

    http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5494 The 12th Zhejiang Provincial ...

  9. Codeforces Gym101572 B.Best Relay Team (2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017))

    2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017) 今日份的训练,题目难度4颗星,心态被打崩了,会的算法太少了,知 ...

随机推荐

  1. stm32f103ve+BH1750使用教程+oled(HAL库)

    1.硬件:BH1750模块+oled 2.代码:BH1750是标准的iic协议的外设,我这里单独有iic的文件,之后想要实现多个设备共用一个iic. BH1750.c 1 #include " ...

  2. 2021.05.29【NOIP提高B组】模拟 总结

    T1 题意:给你一个图,可以不花代价经过 \(K\) 条边,问从起点到终点的最短路 考试的想法:设 \(dis_{i,j}\) 表示从起点免费了 \(j\) 条边到 \(i\) 的最短路 然后直接跑 ...

  3. Eclipse for Python开发环境部署

    Eclipse for Python开发环境部署 工欲善其事,必先利其器. 对开发人员来说,顺手的开发工具必定事半功倍.自学编程的小白不知道该选择那个开发工具,Eclipse作为一个功能强大且开源免费 ...

  4. 纯css就能实现可点击切换的轮播图,feel起来很丝滑

    前言 轮播图经常会在项目里用到,但是实际上用到的轮播图都是比较简单的,没有复杂的特效,这个时候如果去引入swiper那些库的话,未免就有点杀鸡焉用牛刀了. 所以不如自己手写一个,而今天我要分享的一种写 ...

  5. Array 数组filter()方法,遍历数组返回符合条件的一个新数组

    <script> const arr = [ { id: 1, name: "aa", isDone: false }, { id: 2, name: "bb ...

  6. OpenAPI 3.0 规范-食用指南

    概述 OpenAPI 3.0 规范由 8 个根对象组成: openapi info servers paths components security tags externalDocs OpenAP ...

  7. RPA人力资源简历筛选机器人

    简历自动筛选及分析机器人,支持前程无忧.猎聘 1.自动登录招聘网站 2.自动填充简历筛选条件 3.RPA依次读取所筛选的简历信息 4.自动将简历数据复制到本地文档中 5.完成简历信息收集及分析表 6. ...

  8. 简单ELK配置实现生产级别的日志采集和查询实践

    概述 生产问题 集群规模如何规划? 集群中节点角色如何规划? 集群之脑裂问题如何避免? 索引分片如何规划? 分片副本如何规划? 集群规划 准备条件 先估算当前系统的数据量和数据增长趋势情况. 现有服务 ...

  9. flex大法:一网打尽所有常见布局

    flex全称Flexible Box模型,顾名思义就是灵活的盒子,不过一般都叫弹性盒子,所有PC端及手机端现代浏览器都支持,所以不用担心它的兼容性,有了这玩意,妈妈再也不用担心我们的布局. 先简单介绍 ...

  10. 宝塔Linux面板安装教程

    宝塔Linux面板安装教程 安装要求: 内存:512M以上,推荐768M以上(纯面板约占系统60M内存) 硬盘:300M以上可用硬盘空间(纯面板约占20M磁盘空间) 系统:CentOS 7.1+ (U ...