zoukankan      html  css  js  c++  java
  • UVALive3211- Now or later(二分+2-SAT)

    题目链接


    题意:有n架飞机。每架飞机都能够选择早着陆和晚着陆两种方式之中的一个,且必须选择一种。

    任务就是安排全部飞机着陆时。相邻两个着陆时间间隔的最小值尽量大。

    思路:用二分处理最小值尽量大。该题目能够转化为是否存在一个调度方案,使得相邻两个着陆时间差总是不小于P,进一步转化为随意两个着陆时间差总是不小于P。

    ,如果布尔变量xi表示第i架飞机是否早着陆。唯一限制就是“时间差小于P的两个着陆时间不能同一时候满足。每一组不能同一时候满足的着陆时间相应一个子句,则整个约束条件相应于2-SAT问题的实例。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int MAXN = 2005;
    
    struct TwoSAT{
        int n;
        vector<int> g[MAXN * 2];
        bool mark[MAXN * 2];
        int s[MAXN * 2], c;
    
        bool dfs(int x) {
            if (mark[x^1]) return false;
            if (mark[x]) return true;
            mark[x] = true;
            s[c++] = x;
            for (int i = 0; i < g[x].size(); i++)
                if (!dfs(g[x][i])) return false;
            return true;
        }
    
        void init(int n) {
            this->n = n;
            for (int i = 0; i < n * 2; i++) 
                g[i].clear();
            memset(mark, 0, sizeof(mark));
        }
    
        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;
        }
    };
    
    TwoSAT solver;
    int n, T[MAXN][2];
    
    bool test(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() {
        while (scanf("%d", &n) != EOF) {
            memset(T, 0, sizeof(T));
            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 mid = L + (R - L + 1) / 2;
                if (test(mid)) 
                    L = mid; 
                else 
                    R = mid - 1;
            }
            printf("%d
    ", L); 
        }     
        return 0;
    }
    


  • 相关阅读:
    vue使用百度地图
    Genymotion模拟器使用camera
    angular集成tinymce
    react-native环境搭建
    linux系统下安装ssl证书(tomcat)
    vue图片上传及java存储图片(亲测可用)
    那些年vue踩过的坑
    垃圾分类装置仿真实训
    《报任安书》文言文化常识闯关游戏·网络版
    《报任安书》文言文化常识闯关游戏
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/7190058.html
Copyright © 2011-2022 走看看