题意:有n架飞机需要着陆,每架飞机都可以选择“早着陆”或“晚着陆”两种方式,第i架飞机早着陆时间为Ei,晚着陆时间为Li,不得在其他时间着陆。你的任务是为这些飞机安排着陆方式,使得整个着陆计划尽量安全。换言之,如果把所有飞机的实际着陆时间从小到大排序,相邻两个着陆时间间隔的最小值应尽量大。
思路:这是刘汝佳白书上的2-SAT例题,用的书上的模板,思路也按他的写了。
“最小值尽量大”的典型处理方法是二分查找最终答案P。这样原来的问题转换为判定为题“是否存在一个调度方案,使得相邻两个着陆时间差总是不小于P”,而这个问题可以进一步转换为:任意两个着陆时间差总是不小于P。令bool变量xi表示第i架飞机是否早着陆,则唯一的限制就是“时间差小于P的两个着陆时间不能同时满足”。每一组不能同时满足的着陆时间对应于一个子句,则整个约束条件对应于一个2-SAT问题的实例,包含n个变量和n*(n-1)/2个子句。
#include<cstring> #include<string> #include<fstream> #include<iostream> #include<iomanip> #include<cstdio> #include<cctype> #include<algorithm> #include<queue> #include<map> #include<set> #include<vector> #include<stack> #include<ctime> #include<cstdlib> #include<functional> #include<cmath> using namespace std; #define PI acos(-1.0) #define MAXN 2010 #define eps 1e-7 #define INF 0x3F3F3F3F //0x7FFFFFFF #define LLINF 0x7FFFFFFFFFFFFFFF #define seed 1313131 #define MOD 1000000007 #define ll long long #define ull unsigned ll #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 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)); } //x = xval or y = yval 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 fuck; int n, T[MAXN][2]; bool gao(int diff){ int i, j; fuck.init(n); for(i = 0; i < n; i++){ for(int a = 0; a < 2; a++){ for(j = i + 1; j < n; j++){ for(int b = 0; b < 2; b++){ if(abs(T[i][a] - T[j][b]) < diff) fuck.add_clause(i, a ^ 1, j, b ^ 1); } } } } return fuck.solve(); } int main(){ int i, j; while(scanf("%d", &n) != EOF){ int l = 0, r = 0; for(i = 0; i < n; i++){ scanf("%d%d", &T[i][0], &T[i][1]); int temp = max(T[i][0], T[i][1]); r = max(r, temp); } int ans; while(l <= r){ int mid = (l + r) / 2; if(gao(mid)){ if(!gao(mid + 1)){ ans = mid; break; } else l = mid + 1; } else r = mid - 1; } printf("%d\n", ans); } return 0; }
时间: 2024-10-09 02:23:45