5920: 喷水装置(贪心)

 

长 L米,宽 W 米的草坪里装有 n个浇灌喷头。每个喷头都装在草坪中心线上(离两边各 W2 米)。我们知道每个喷头的位置(离草坪中心线左端的距离),以及它能覆盖到的浇灌范围。

请问:如果要同时浇灌整块草坪,最少需要打开多少个喷头?

输入

 

输入包含若干组测试数据。

第一行一个整数 T 表示数据组数;

每组数据的第一行是整数 n、L 和 W;

接下来的 n 行,每行包含两个整数,给出一个喷头的位置和浇灌半径(上面的示意图是样例输入第一组数据所描述的情况)。

对于 100% 的数据,n≤15000。

输出

 

对每组测试数据输出一个数字,表示要浇灌整块草坪所需喷头数目的最小值。如果所有喷头都打开也不能浇灌整块草坪,则输出−1。

样例输入

样例输出

解题思路: 贪心思想 选能够覆盖该点的最右边的线段,然后更新覆盖点使覆盖点变为该线段的最右边的饿位置

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int t,num;
 5 int n,L,W;
 6 const int N=15005;
 7 
 8 struct Node{
 9     double x,y;
10     bool operator<(const Node&X) const{
11         return x<X.x;
12     }
13 }A[N];
14 
15 void cultilate(){
16     sort(A+1,A+1+num);
17     double weizhi=0.0;
18     int res=0,ans=1,vis=1;
19     while(weizhi<L){
20         res++;
21         double temp=weizhi;
22         while(temp>=A[ans].x&&ans<=num){
23             if(A[ans].y>weizhi) weizhi=A[ans].y;
24             ans++;
25         }    ///找能够覆盖该点的最右边的位置
26 //        cout << ans << " " << num << endl;
27 //        cout << weizhi << endl;
28 //        cout << res << endl;
29         if(ans>num) break;
30         if(temp==weizhi) {vis=0;break;}
31     }
32     if(weizhi<L) vis=0;
33     if(vis) cout << res << endl;
34     else cout << -1 << endl;
35 }
36 
37 int main()
38 {
39     ios::sync_with_stdio(false);
40     cin>>t;
41     while(t--){
42         cin>>n>>L>>W;
43         num=0;
44         for(int i=1,d1,d2;i<=n;i++){
45             cin>>d1>>d2;
46             if(2*d2<=W) continue;
47             else{
48                 double w1=d1-sqrt(d2*d2-W*W/4.0);
49                 double w2=d1+sqrt(d2*d2-W*W/4.0);
50                 A[++num]={w1,w2};
51             }
52         }
53         cultilate();
54     }
55     return 0;
56 }
View Code

 

 

原文地址:https://www.cnblogs.com/qq-1585047819/p/11231998.html