UVA 1146 2-SAT

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

*/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值