飞机调度,白书P325LA3211(2-SAT算法, 二分查找“最小值尽量大”)
2017-11-16 00:55
316 查看
本题是较难处理的一道题涉及的知识点比较多。需要反复复习。
知识总结:
1.关于TwoSAT算法:对于两个bool型变量a,b,共有四种组合情况。
a = true; b = true;
a = true; b = false;
a = false; b = true;
a = false; b = false;
对于任意且命题,例如a且非b,则有a = true可直接推出b = false;反之亦然;
对于任意或命题,当前者为假的时候则一定能推出后者为真, 当后者为假的时候则一定能推出前者为真。
由此,对于每一个条件,都能添加两条有向边。
2.核心处理:
切记x^
4000
1不改变x的值。
3.二分查找算法:
知识总结:
1.关于TwoSAT算法:对于两个bool型变量a,b,共有四种组合情况。
a = true; b = true;
a = true; b = false;
a = false; b = true;
a = false; b = false;
对于任意且命题,例如a且非b,则有a = true可直接推出b = false;反之亦然;
对于任意或命题,当前者为假的时候则一定能推出后者为真, 当后者为假的时候则一定能推出前者为真。
由此,对于每一个条件,都能添加两条有向边。
2.核心处理:
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); } 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);
切记x^
4000
1不改变x的值。
3.二分查找算法:
while(L < R) { int M = L + (R-L+1)/2; if(test(M)) L = M; else R = M-1; }
// LA3211 Now or Later // Rujia Liu #include<cstdio> #include<vector> #include<cstring> using namespace std; const int maxn = 2000 + 10; 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; } }; ///////// 题目相关 #include<algorithm> 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) == 1 && n) { 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 M = L + (R-L+1)/2; if(test(M)) L = M; else R = M-1; } printf("%d\n", L); } return 0; }
相关文章推荐
- UVA Live 3211飞机调度问题-二分+2-SAT
- 【算法-查找之二】二分查找
- 数据结构与算法-二分查找
- 【算法】二分查找
- 二分查找算法-精简 稳定
- |算法讨论|二分查找 学习笔记
- 数据结构与算法题目集(中文)4-10 二分查找 (20分)
- 算法 查找算法--二分查找
- 二分查找算法java
- 二分查找算法和链表相关小技巧
- java数据结构与算法-递归二分查找
- 算法学习-归并排序和二分查找
- STL中的二分查找算法(binary_search lower_bound upper_bound equal_range)
- 算法 —— 二分查找
- 程序员必须掌握的十种算法---二分查找算法
- [Python]二分查找算法实现
- 【数据结构与算法】二分查找
- 算法-符号表的实现(顺序查找和二分查找)
- 二分查找——算法系列
- 基于数组二分查找算法的实现