题目大意:
有n架飞机需要着陆,每架飞机有早着陆和晚着陆两种选择,你要为这些飞机安排着陆计划,使得任意两架飞机的着陆时间间隔的最小值尽量大。
分析:
首先,对于这种最小值最大化大问题,我们很自然的会想到二分答案的方法,对于每一个二分出来的答案,如果存在任意两架飞机的某两种着陆方式时间间隔小于当前二分出来的答案,则说明这两架飞机不能同时选择当前方案,则整个问题就转化为一个经典的2-Sat问题模型。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2000 + 10;
struct Twosat {
int n;
vector<int> G[maxn*2];
bool mark[maxn*2];
int S[maxn*2], c;
inline void init(int n) {
this -> n = n;
for(int i=0; i<n*2; i++) G[i].clear();
memset(mark, 0, sizeof(mark));
}
bool dfs(int x) {
if(mark[x]) return true;
if(mark[x^1]) return false;
mark[x] = 1;
S[c++] = x;
for(int i=0; i<G[x].size(); i++)
if(!dfs(G[x][i])) return false;
return true;
}
//x = xval or y = yval
void add_clause(int x, int xval, int y, int yval) {
x = x*2 + xval;
y = y*2 + yval;
G[x^1].push_back(y);
G[y^1].push_back(x);
}
bool solve() {
for(int i=0; i<n*2; i+=2)
if(!mark[i] && !mark[i^1]) {
c = 0;
if(!dfs(i)) {
while(c > 0) mark[S[--c]] = false;
if(!dfs(i^1)) return false;
}
}
return true;
}
}solver;
int n, T[maxn][2];
bool check(int diff) {
solver.init(n);
for(int i=0; i<n; i++) for(int a=0; a<2; a++)
for(int j=i+1; j<n; j++) for(int b=0; b<2; b++)
if(abs(T[i][a] - T[j][b]) < diff) solver.add_clause(i, a^1, j, b^1);
return solver.solve();
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.txt", "r", stdin);
freopen("ans.txt", "w", stdout);
#endif
while(scanf("%d", &n) == 1 && n) {
int L = 0, R = 0;
for(int i=0; i<n; i++)
for(int a=0; a<2; a++)
scanf("%d", &T[i][a]), R = max(R, T[i][a]);
while(L < R) {
int M = L + (R-L+1) / 2;
if(check(M)) L = M; else R = M-1;
}
printf("%d\n", L);
}
return 0;
}