喷水装置(二) 区间长度贪心

来源:互联网 发布:淘宝老客户营销短信 编辑:程序博客网 时间:2024/05/16 11:58

描述
有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=10000)个点状的喷水装置,每个喷水装置i喷水的效果是让以它为中心半径为Ri的圆都被润湿。请在给出的喷水装置中选择尽量少的喷水装置,把整个草坪全部润湿。
输入
第一行输入一个正整数N表示共有n次测试数据。
每一组测试数据的第一行有三个整数n,w,h,n表示共有n个喷水装置,w表示草坪的横向长度,h表示草坪的纵向长度。
随后的n行,都有两个整数xi和ri,xi表示第i个喷水装置的的横坐标(最左边为0),ri表示该喷水装置能覆盖的圆的半径。
输出
每组测试数据输出一个正整数,表示共需要多少个喷水装置,每个输出单独占一行。
如果不存在一种能够把整个草坪湿润的方案,请输出0。
样例输入
22 8 61 14 52 10 64 56 5
样例输出
12


分析:

告诉你喷水的位置和喷射的半径,你可以求出能覆盖矩形草坪在水平方向上的长度,即知道每个喷水的左右端点,剩下的就是求在固定区间内问最少多少个小区间能够覆盖


#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <vector>#include <set>#include <map>#include <stack>#include <string>using namespace std;double len(double a,double b){    return sqrt(a*a-b*b);}int cmp(pair<double,double>a,pair<double,double>b){return a.first < b.first;}int main(){    int t;    cin >> t;    while(t--)    {    int n,w,h;    cin >> n >> w >> h;    vector<pair<double,double> >v;    for(int i = 0;i < n;i++)    {    int x,r;    cin >> x >> r;    double l = len(r,h/2.0);    if(l > h/2.0)    {    pair<double,double>p;        p.first = x-l;        p.second = x+l;        v.push_back(p);    }    }    sort(v.begin(),v.end(),cmp);    int cnt = 0;    double right = 0;        while(right < w)        {        double m = 0.0;        ///求尽可能在已知区间上向右扩展的最大的右端点,使得尽可能使用较少的喷水器就能全部覆盖        for(int i = 0;i < v.size()&&v[i].first <= right;i++)        {                if(v[i].second - right > m)m = v[i].second - right;        }        if(m)        {        cnt++;        right+=m;        }        else        break;///如果扩展不动了,那就说明已经扩展完成了        }        if(right < w)        cout << 0 << endl;        else        cout << cnt << endl;    }return 0;}


#include <iostream>  #include <cstdio>  #include <algorithm>  #include <cstring>  #include <cmath>  #include <vector>  #include <set>  #include <map>  #include <stack>  #include <string>  using namespace std;  double len(double a,double b)  {      return sqrt(a*a-b*b);  }  int cmp(pair<double,double>a,pair<double,double>b)  {      return a.first < b.first;  }  int main()  {      int t;      //ios::sync_with_stdio(false);    cin >> t;      while(t--)      {          int n,w,h;          //cin >> n >> w >> h;          scanf("%d%d%d",&n,&w,&h);        vector<pair<double,double> >v;          for(int i = 0;i < n;i++)          {              int x,r;              //cin >> x >> r;              scanf("%d%d",&x,&r);            double l = len(r,h/2.0);              if(l > h/2.0)              {                  pair<double,double>p;                  p.first = x-l;                  p.second = x+l;                  v.push_back(p);              }          }          sort(v.begin(),v.end(),cmp);          int cnt = 0;          double right = 0;        int top = 0;          while(right < w)          {              double be = right+0.000001;///每次加上0.000001,俩区间有断点,就能区分            for(int i = top;i < v.size();i++)            {            if(v[i].first <= be&&v[i].second >= be)            {            right = v[i].second > right ? v[i].second:right;            }            else if(v[i].first > be)            {            top = i;            break;            }            }            if(be > right) break;            else cnt++;        }          if(right < w)              //cout << 0 << endl;              printf("0\n");        else          //cout << cnt << endl;          printf("%d\n",cnt);    }      return 0;  }








原创粉丝点击