zoukankan      html  css  js  c++  java
  • 【LA3211 训练指南】飞机调度 【2-sat】

    题意

      有n嫁飞机需要着陆。每架飞机都可以选择“早着陆”和“晚着陆”两种方式之一,且必须选择一种。第i架飞机的早着陆时间为Ei,晚着陆时间为Li,不得在其他时间着陆。你的任务是为这些飞机安排着陆方式,使得整个着陆计划尽量安全。话句话说,如果把所有飞机的实际着陆时间按照从早到晚的顺序排列,相邻两个着陆时间间隔的最小值(称为安全间隔)应尽量大。

    分析

      看到最小值最大立刻会想到二分。大体思路很好想,我们二分这个安全间隔,然后判断是否可行。那么这个题的难点就变为如何判断这个安全间隔是否可行。

      n架飞机,每架飞机要么选择早起飞要么选择晚起飞,对应着2-sat问题中n个布尔型变量每个变量要么为真,要么为假。那么那m个限制条件是什么呢? 

      我们假设当前二分的安全间隔是P,那么如果两个时间小于P,则说明两个时间不能同时选择。比如说Ei和Lj的时间差小于P,则说明Ei和Lj不能同时选择。所以要么选择Li和Lj,要么选择Ei和Ej,要么选择Li和Ej。也就是说,xi晚起飞或者xj早起飞。到这里这个题就完全转化为了2-sat问题。

      下面是AC的代码

      

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <vector>
     6 #include <cmath>
     7 
     8 using namespace std;
     9 const int maxn=2000+10;
    10 struct TwoSAT{
    11     int n;
    12     vector<int>G[2*maxn];
    13     bool mark[maxn*2];
    14     int S[maxn*2],c;
    15     bool dfs(int x){
    16         if(mark[x^1])return false;
    17         if(mark[x])return true;
    18         mark[x]=true;
    19         S[c++]=x;
    20         for(int i=0;i<G[x].size();i++){
    21             if(!dfs(G[x][i]))return false;
    22         }
    23         return true;
    24     }
    25     void init(int n){
    26         this->n=n;
    27         for(int i=0;i<n*2;i++)G[i].clear();
    28         memset(mark,0,sizeof(mark));
    29     }
    30     void add_clause(int x,int xval,int y,int yval){
    31         x=x*2+xval;
    32         y=y*2+yval;
    33         G[x^1].push_back(y);
    34         G[y^1].push_back(x);
    35     }
    36 
    37     bool solve(){
    38         for(int i=0;i<n*2;i+=2){
    39             if(!mark[i]&&!mark[i+1]){
    40                 c=0;
    41                 if(!dfs(i)){
    42                     while(c>0)mark[S[--c]]=false;
    43                     if(!dfs(i+1))return false;
    44                 }
    45             }
    46         }
    47         return true;
    48     }
    49 }solver;
    50 int n,T[maxn][2];
    51 bool test(int diff){
    52     solver.init(n);
    53     for(int i=0;i<n;i++){
    54         for(int a=0;a<2;a++){
    55             for(int j=i+1;j<n;j++){
    56                 for(int b=0;b<2;b++){
    57                     if(abs(T[i][a]-T[j][b])<diff)solver.add_clause(i,a^1,j,b^1);
    58                 }
    59             }
    60         }
    61     }
    62     return solver.solve();
    63 }
    64 int main(){
    65     while(scanf("%d",&n)!=EOF&&n){
    66         int L=0,R=0;
    67         for(int i=0;i<n;i++){
    68             for(int a=0;a<2;a++){
    69                 scanf("%d",&T[i][a]);
    70                 R=max(R,T[i][a]);
    71             }
    72         }
    73         while(L<R){
    74             int M=L+(R-L+1)/2;
    75            // cout<<L<<" "<<R<<endl;
    76             if(test(M))L=M;
    77             else
    78                 R=M-1;
    79         }
    80         printf("%d
    ",L);
    81     }
    82 return 0;
    83 }
    View Code
  • 相关阅读:
    简体繁体互译代码段:
    require.js使用baseUrl + paths导入文件配置的3种方法
    vue + vue-router + vue-resource 基于vue-cli脚手架 --->笔记
    解决webstorm卡顿问题
    js 函数闭包内部返回函数体调用方法难点解答
    java学习笔记之位运算符
    java集合类学习笔记之LinkList
    java集合类学习笔记之ArrayList
    java学习笔记之对象序列化
    springboot集成巨杉数据库
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/9310922.html
Copyright © 2011-2022 走看看