噴水装置(二)

5031 ワード

噴水装置(二)
時間制限:
3000 ms|メモリ制限:
65535 KB
難易度:
4
説明
横方向の長さw、縦方向の長さhの芝生があり、その横中心線上の異なる位置にn(n<=10000)個の点状の噴水装置が装着されており、各噴水装置iの噴水効果は、それを中心とした半径Riの円を濡らすことである.与えられた噴水装置の中からできるだけ少ない噴水装置を選択し、芝生全体を濡らしてください.
入力
1行目に正の整数Nを入力すると、n回のテストデータが共有されます.
各試験データの最初の行には、3つの整数n,w,h,nがn個の噴水装置を表し、wが芝生の横方向の長さを表し、hが芝生の縦方向の長さを表す.
その後のn行には、いずれも2つの整数xiとriがあり、xiはi番目の噴水装置の横座標(左端が0)を表し、riはこの噴水装置が覆うことができる円の半径を表す.
しゅつりょく
各試験データのセットは正の整数を出力し、合計何個の噴水装置が必要かを示し、各出力は単独で1行を占めている.
芝生全体を湿らせる案がない場合は、0を出力してください.
サンプル入力
2
2 8 6
1 1
4 5
2 10 6
4 5
6 5

サンプル出力
1
2
 
    
#include<iostream>
#include<cstdlib>
#include<cmath>
#include <algorithm>
using namespace std;
struct S 
{
	double a;
	double b;
}t[1000000];
int cmp(const S& c,const S& d)
{
	return c.a==d.a&&c.b>d.b||c.a<d.a;
}
int main()
{
	int N,n,w,h,i,k;
	double x,y,end,temp,max1=0;
	cin >> N;
	while (N--)
	{
		k=0;
		cin >> n >> w >> h;
		while(n--)
		{
			cin >> x >> y;
			int d=(int)sqrt(y*y-(h/2.0)*(h/2.0));
			if (y>h/2.0&&x+d>=0&&x-d<=w)
			{
				t[k].a=x-d;
				t[k++].b=x+d;
			}
		}
		sort(t,t+k,cmp);
		i=0;
		int cnt=0;
		end=t[0].a;
		while (end<=w&&i<k)
		{
			temp=end;
			while (t[i].a<=end&&i<k)
			{
				if (temp<t[i].b)
				{
					max1=t[i].b;
					temp=t[i].b;
				}
				i++;
			}
			end=temp+1;
			cnt++;
		}
		if (t[0].a>0||max1<w)
		{
			cout << 0 << endl;
			continue;
		}
		cout << cnt << endl;
	}
	return 0;
}

コード:

#include <stdio.h>
#include <math.h>
#include <algorithm>
using std::sort;
struct node{
	double le, ri;
}s[1005];
int cmp(node a, node b)
{
	return a.le < b.le;
}
int main()
{
	int n, t;
	double w, h;
	scanf("%d", &t);
	while(t --){
		scanf("%d%lf%lf", &n, &w, &h);
		h /= 2;  //   2
		int i, j;
		double temp, r;
		for(i = 0, j = 0; i < n; i ++){
			scanf("%lf%lf", &temp, &r);
			if(r <= h) continue;//    ,             
			else{
				double temp1 = sqrt(r*r-h*h);//            
				s[j].le = temp -temp1;//   
				s[j++].ri = temp+temp1;//   
			}
		}
		sort(s, s+j, cmp);//  
	//	for(i = 0; i < j; i ++){
	//		printf("%lf %lf..
", s[i].le, s[i].ri); // } if(s[0].le > 0) {printf("0
"); continue;} // 0, 0 , 0 double end = 0; i = 0; int cou = 0; while(end <= w&&i < j&&cou <= n){// temp = end; while(s[i].le <= end&&i <j ){ if(s[i].ri > temp) temp = s[i].ri; i++; } end = temp+0.000001;// 0.00001, , ++cou; } if(end < w||cou > n){// cou>n , end<w w printf("0
"); } else{ printf("%d
", cou); } } return 0; }
 
    
 
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
double r,x,y,width,height;
class Circle
{
public:
	Circle(double x,double r):x(x),r(r){}
	double Left() const{
		if(r*r-height*height/4<0) return x;return x-sqrt(r*r-(height*height/4));}
	double Right() const{if(r*r-height*height/4<0) return x;return x+sqrt(r*r-(height*height/4));}
	friend ostream & operator<<(ostream& out,const Circle& circle);
private:
	double x,r;
};
ostream & operator<<(ostream& out,const Circle& circle)
{
	out<<circle.x<<" "<<circle.r;
	return out;
}
struct CircleLess
{
	bool operator()(const Circle& c1,const Circle& c2)
	{
		return c1.Right()<c2.Right();
	}
};

int main()
{

	int m;
	cin>>m;
	while(m--)
	{
		int n;
		
		vector<Circle> Rs;
		cin>>n>>width>>height;
		Rs.reserve(n);
		
		
		while(n--)
		{
			cin>>x>>r;
			Rs.push_back(Circle(x,r));
		}
		sort(Rs.begin(),Rs.end(),CircleLess());
		vector<int> choosed;
		choosed.push_back(-1);
		double len=0;
		try{
			while(len<width)
			{
				int last=-1;
				for(vector<Circle>::size_type i=choosed.back()+1;i!=Rs.size();i++)
				{
					if (Rs[i].Left()<=len)
					{
						//cout<<Rs[i].Left()<<endl;
						last=i;
					}
				}
				if (last==-1) throw -1;
				else
				{
					choosed.push_back(last);
					len=Rs[last].Right();
				}
			}	
			cout<<choosed.size()-1<<endl;
		
		}catch(...)
		{
			cout<<0<<endl;
		}
	}

}