UVA 1146
题目链接:
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=36009
题意:
n架飞机,有两个降落时间任选一个。
选择一种合理的降落时间分配方案,使得相邻降落的两架飞机降落时间最小间隔最大。
思路:
看了题解,也不知道1A有木有效果。
二分时间,判断是否合法。因为一架飞机降落只有两种状态,所以二分时间后,在时间间隔不合法的两个点之间处理。2-SAT版。
二分新姿势get
源码:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
#define gmax(a,b) ((a) > (b) ? (a) : (b))
#define gmin(a,b) ((a) < (b) ? (a) : (b))
const int MAXN = 2000 + 5;
int T[MAXN][2];
int n;
vector<int>lin[MAXN * 2];
bool valid[MAXN * 2];
stack<int>sta;
void add(int u, int uval, int v, int vval)
{
u = 2 * u + uval;
v = 2 * v + vval;
lin[u^1].push_back(v);
lin[v^1].push_back(u);
}
bool dfs(int u)
{
if(valid[u^1]) return false;
if(valid[u]) return true;
valid[u] = true;
sta.push(u);
for(int i = 0 ; i < (int)lin[u].size() ; i++){
if(!dfs(lin[u][i])) return false;
}
return true;
}
bool solve(int t)
{
for(int i = 0 ; i < 2 * n ; i++)
lin[i].clear();
for(int i = 0 ; i < n ; i++){
for(int j = i + 1 ; j < n ; j++){
for(int k1 = 0 ; k1 < 2 ; k1++){
for(int k2 = 0 ; k2 < 2 ; k2++){
if(abs(T[i][k1] - T[j][k2]) < t)
add(i, k1, j, k2);
}
}
}
}
while(!sta.empty()) sta.pop();
memset(valid, false, sizeof(valid));
for(int i = 0 ; i < 2 * n ; i += 2){
if(!valid[i] && !valid[i^1]){
if(!dfs(i)){
while(!sta.empty()){
int org = sta.top(); sta.pop();
valid[org] = false;
if(org == i) break;
}
if(!dfs(i^1)) return false;
}
}
}
return true;
}
int main()
{
while(scanf("%d", &n) != EOF)
{
int L, R;
L = R = 0;
for(int i = 0 ; i < n ; i++){
scanf("%d%d", &T[i][0], &T[i][1]);
R = gmax(R, T[i][1]);
}
// printf("R = %d, L = %d\n", R, L);
while(L < R){
int mid = L + (-L + R + 1) / 2;
if(solve(mid)) L = mid;
else R = mid - 1;
}
// printf("after 2-fen R = %d, L = %d\n", R, L);
// if(solve(R))
printf("%d\n", R);
// else
// printf("%d\n", L);
}
return 0;
}
/*
10
44 156
153 182
48 109
160 201
55 186
54 207
55 165
17 58
132 160
87 197
*/