uva10382(贪心算法---区间覆盖问题)
2017-08-23 21:36
155 查看
https://vjudge.net/problem/UVA-10382(uva10382 点击打开题目链接)
区间覆盖问题:数轴上有n个闭区间【a-i,b-i】(i是下标),选择尽量少的区间覆盖一条指定线段【s,t】。
思路:转化成草坪矩形上边界(或下边界)的区间覆盖问题。
分析:因为圆的圆心都在草坪中间,所以如果能覆盖矩形的上边界,就一定能覆盖矩形的下边界。每个圆形洒水器的洒水范围(即n个闭区间)可以通过勾股定理求得,因此就转化为了在矩形上边界这条线段(长度为l)上的区间覆盖问题。
(算法竞赛入门经典)该类题的突破口仍然是区间包含和排序扫描,不过要先进行一次预处理。每个区间在【s,t】外的部分都应该先被切掉,因为他们的存在是毫无意义的。预处理后,在相互包含的情况下,小区间显然不应该考虑。(明白是明白了,不过具体到题目就不清楚怎么预处理了)。
把各区间按照a(区间左侧端点)从小到大排序。如果区间1的左端点大于s,无解(因为其他区间的起点更大,不可能覆盖到s点),否则选择起点小于s的最长区间(至于怎么选择最长区间,这道题就卡在这儿了,看了好多题解代码,最后终于理解的差不多了)。选择此区间【a-i,b-i】后,新的起点应该设置为b-i,并且忽略所有区间在b-i之前的部分,就像预处理一样。
代码:
贪心—区间覆盖,还差的很远啊,继续加油吧。
区间覆盖问题:数轴上有n个闭区间【a-i,b-i】(i是下标),选择尽量少的区间覆盖一条指定线段【s,t】。
思路:转化成草坪矩形上边界(或下边界)的区间覆盖问题。
分析:因为圆的圆心都在草坪中间,所以如果能覆盖矩形的上边界,就一定能覆盖矩形的下边界。每个圆形洒水器的洒水范围(即n个闭区间)可以通过勾股定理求得,因此就转化为了在矩形上边界这条线段(长度为l)上的区间覆盖问题。
(算法竞赛入门经典)该类题的突破口仍然是区间包含和排序扫描,不过要先进行一次预处理。每个区间在【s,t】外的部分都应该先被切掉,因为他们的存在是毫无意义的。预处理后,在相互包含的情况下,小区间显然不应该考虑。(明白是明白了,不过具体到题目就不清楚怎么预处理了)。
把各区间按照a(区间左侧端点)从小到大排序。如果区间1的左端点大于s,无解(因为其他区间的起点更大,不可能覆盖到s点),否则选择起点小于s的最长区间(至于怎么选择最长区间,这道题就卡在这儿了,看了好多题解代码,最后终于理解的差不多了)。选择此区间【a-i,b-i】后,新的起点应该设置为b-i,并且忽略所有区间在b-i之前的部分,就像预处理一样。
代码:
#include <iostream> #include <string> #include <cstring> #include <algorithm> #include <cmath> #include <vector> #include <cstdio> #include <map> #include <cstdlib> #define pi 2*acos(0) using namespace std; const int maxn = 10000 + 10; struct node { double l,r; node(double ll,double rr):l(ll),r(rr){} bool operator < (const node x)const//重载小于运算符,进行排序(该题是按照左侧端点从小到大排序,有时候也按照右侧端点排序) { return l < x.l; } }; vector<node> v; int main() { int n; double l,w; while(~scanf("%d%lf%lf",&n,&l,&w)) { v.clear();//清空很重要 int a,b; for(int i = 0;i < n;i++) { scanf("%d%d",&a,&b); if(b * 2.0 <= w)//特例判断,如果整个圆都在矩形里面,一定不选 continue; double p = sqrt((b*1. 4000 0)*(b*1.0) - (w/2.0)*(w/2.0));//勾股定理,求出半个区间长度,这里结合图形好好理解,如果理解不了,就做不出题目来。 v.push_back(node(a - p,a + p));//将区间长度存入容器 } sort(v.begin(),v.end());//切记:排序!!! int ans = 1; double sl = 0.0,sr = 0.0; //之前看的代码有这一部分,去掉之后仍然ac,因为下面的循环包含了这种情况 // if(v.empty() || v[0].l > 0.0) // { // printf("-1\n"); // continue; // } for(int i = 0;i < v.size();i++) { if(v[i].l <= sl)//左侧的点比左界限小,但是要选一个最长的区间 { //如果有多组数据,都满足左侧点比左界限小,那就一直更新右界限,选择最大的区间。 sr = max(sr,v[i].r); } else { //直到左侧的点比左界限大了,计数加一 ans++; sl = sr;//新的起点(或者需要维护的点)设置为‘b-i’(即sr). if(v[i].l > sl)//如果新的区间左侧端点大于起点,不符合情况,跳出循环 break; sr = v[i].r;//否则,更新右边界 } if(sr >= l) break; } if(sr >= l) printf("%d\n",ans); else printf("-1\n"); } return 0; }
贪心—区间覆盖,还差的很远啊,继续加油吧。
相关文章推荐
- 基于贪心算法的几类区间覆盖问题
- 基于贪心算法的几类区间覆盖问题:(侵删)
- 基于贪心算法的几类区间覆盖问题
- 基于贪心算法的几类区间覆盖问题
- 基于贪心算法的几类区间覆盖问题
- 基于贪心算法的几类区间覆盖问题
- 基于贪心算法的几类区间覆盖问题
- UVa 10382 - Watering Grass(贪心算法,区间覆盖问题)
- 基于贪心算法的几类区间覆盖问题
- 基于贪心算法的几类区间覆盖问题
- 基于贪心算法的几类区间覆盖问题
- 基于贪心算法的几类区间覆盖问题
- 基于贪心算法的几类区间覆盖问题
- 基于贪心算法的几类区间覆盖问题
- 基于贪心算法的几类区间覆盖问题
- 基于贪心算法的几类区间覆盖问题
- 基于贪心算法的几类区间覆盖问题
- 基于贪心算法的几类区间覆盖问题
- 基于贪心算法的几类区间覆盖问题
- 基于贪心算法的几类区间覆盖问题