算法入门经典关于区间覆盖的讲解:
8.4.6:区间覆盖问题
数轴上有n个区间[ai,bi],选择尽量少的区间覆盖一条指定线段[s,t]。
【分析】
突破口是区间的包含和排序扫描,不过要先进行一次预处理。每个区间在[s,t]外的部分应该首先被切除掉,因为他们的存在是没有意义的。在预处理后,在相互包含的情况下,小区间显然不应该考虑。
把区间按照a从小到大排序。如果区间1的七点不是s,无解,否则选择起点在s的最长区间。选择此区间[ai,bi]后,新的起点应该设置为bi,并且忽略所有区间在bi之前的部分,就像预处理一样。仍然只需要一次扫描。
题意:给予几条线段的坐标,x轴上的。求可以覆盖[0,M]线段的最少区间数和坐标。
方法和代码解释:贪心,1、先排序,左坐标小到大,右坐标从大到小。确保选到的区间是最大的。
2、注意这种情况,
我们选3而不选2,这就是程序中pre_l的作用。
AC代码:
#include <iostream> #include <iomanip> #include <string> #include <cstring> #include <cstdio> #include <queue> #include <stack> #include <algorithm> #include <cmath> #include <ctime> using namespace std; struct coo { int l; int r; }; const int maxn = 100000+10; int cmp(const void *a, const void *b) { coo *x = (coo *)a; coo *y = (coo *)b; if ((*x).l == (*y).l) return (*y).l - (*x).l; return (*x).l - (*y).l; } coo p[maxn], ans[maxn]; int main() { #ifdef Local freopen("a.txt", "r", stdin); #endif int t = 0; cin >> t; while (t--) { int M = 0, num = 0, i = 0, flag = 0;//num是坐标的数量 cin >> M; for (num = 0;; num++) { cin >> p[num].l >> p[num].r; if (p[num].l + p[num].r == 0) break; } qsort(p, num, sizeof(p[0]), cmp); int cl = 0, cr = 0, count = 0, pre_l = 0; for (i = 0; i < num; i++)//遍历 { if (!i && p[i].l > 0) { flag = 1; break; } if (p[i].r > cr) { cl = p[i].l; cr = p[i].r; }//设置为新的起点 if (i+1 < num && p[i+1].l > pre_l) { pre_l = cr; ans[count].l = cl; ans[count].r = cr; count++; if (cr >= M) break; if (p[i+1].l > cr) { flag = 1; break; } } if (i == num - 1) { if (cr < M || p[i].l > pre_l) flag = 1; else { ans[count].l = cl; ans[count].r = cr; count++; } } } if (flag) cout << ‘0‘ << endl; else { cout << count << endl; for (i = 0; i < count; i++) cout << ans[i].l << ‘ ‘ << ans[i].r << endl; } if (t) cout << endl; } return 0; }
错误:1、数组要定义在外边,因为很大,定义在里边会栈溢出。
2、p[i+1].l > cr 写错成了 > cl 。
UVa 10020 - Minimal coverage(区间覆盖、贪心)
原文地址:http://blog.csdn.net/u013545222/article/details/24648887