题意:
有一个飞机场,有两条待飞跑到w和e,一条起飞跑道,每一时刻只能起飞一架飞机,然后有w[i]和e[i]架飞机进入w和e跑道,飞机编号从0开始,问说如何安排起飞可以使得飞机编号的最大值最小。
解析:
由于是最大值最小化问题,所以要用到二分求解。二分枚举最大值 limit 判断该最大值是否满足题目所给的条件。
这题看来别人的代码理解了好久,感觉这题充满了技巧。
设 have 表示的是当前时刻先不发送飞机,预留下空间的数目,既然是预留下空间那么每个时刻都可以满足最优。
但是还有3种情况要考虑,
1. 如果当前的 sume=0且sumw>0 表示当前e通道无法发送飞机,只能w通道发送飞机,sumw–。
2. 反之如果当前的 sumw=0且sume>0 表示当前w通道无法发送飞机,只能e通道发送飞机,sume–。
3. 如果 sumw+sume>have ,如果两边的飞机数目大于预留的飞机数目表示当前还可以发送飞机,have++。那么什么情况下是不满足题目条件的呢?
当 overe+overw>have ,表示当前的超出的飞机数目大于预留的空间,那么不符合条件。
AC代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
typedef long long ll;
const int N = 5e3 + 10;
int w[N], e[N];
int n;
bool judge(int lim) {
int sumw, sume, have;
sumw = sume = have = 0;
for(int i = 0; i < n; i++) {
sumw += w[i], sume += e[i];
int overw = max(sumw-lim, 0);
int overe = max(sume-lim, 0);
if(overw + overe > have) return false;
if(sumw == 0 && sume > 0) sume--;
else if(sume == 0 && sumw > 0) sumw--;
else if(sumw && sume && sumw + sume > have) have++;
}
return true;
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
int maxv = 0;
for(int i = 0; i < n; i++) {
scanf("%d%d", &w[i], &e[i]);
maxv += max(w[i], e[i]);
}
int L = 1, R = maxv;
while(L <= R) {
int M = (L+R)/2;
if(judge(M)) R = M-1;
else L = M+1;
}
printf("%d\n", L-1);
}
return 0;
}