【LA3211 訓練指南】飛機調度 【2-sat】
阿新 • • 發佈:2018-07-14
truct max ostream out oid 問題 如何判斷 clear rdquo
題意
有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> 6View Code#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\n",L); 81 } 82 return 0; 83 }
【LA3211 訓練指南】飛機調度 【2-sat】