LA3211 训练指南飞机调度 2-sat
Posted lqllulu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于LA3211 训练指南飞机调度 2-sat的主要内容,如果未能解决你的问题,请参考以下文章
UVALive3211- Now or later(二分+2-SAT)