neerc-2013-Green Energy

題目大意:給你n個槓子,m個x單調遞增的點(就是地形),再給你陽光的偏角a,求最大的被陽光照到的長度(地形和槓子都會擋住陽光),以及槓子放的位置(槓子只能豎直放置) n<=10000 m<=10000 0<a<90


這道題有幾種寫法,一種是座標轉換的 傳送門:http://blog.csdn.net/u012647218/article/details/42714121

還有不是座標轉換的,首先找到最長的那根杆子,先不用着,然後把剩下的槓子一路放過來,具體來說就是先在最前面放一根杆子,然後看太陽光的陰影到哪,就把下一根放哪,直到沒有杆子或者沒有地方放爲止。至於最後那根最高的槓子,就放在最後一根所放的後方(不擋住其餘的)且受益最大的地方就OK了


#include<cmath>
#include<cstdio>
#include<cstring>
#include<cassert>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=10011;
const double pai=M_PI,eps=1e-6;
struct Tp{double x,y;}e[maxn];
struct Tl{double a,b,c;};
double h[maxn]; int n,m; double sk;
void init(){
	int a; scanf("%d",&a); sk=tan(-a*pai/180);
	for (int i=1;i<=n;++i) scanf("%lf",h+i);
	for (int i=1;i<=m;++i) scanf("%lf%lf",&e[i].x,&e[i].y);
}
int sgn(double x){
	if (x+eps>0 && x-eps<0) return 0;
	if (x-eps>0) return 1; return -1;
}
Tp w[maxn]; double *p[maxn];
Tp getp(Tl l1,Tl l2){
	if (!sgn(l1.a-l2.a)){
		double tmp=l2.a/l1.a; l1.b*=tmp; l1.c*=tmp;
		Tp o; o.y=(l2.c-l1.c)/(l1.b-l2.b); o.x=(l2.c+o.y*l2.b)/(-l2.a); return o;
	}else{
		double tmp=l2.b/l1.b; l1.a*=tmp; l1.c*=tmp;
		Tp o; o.x=(l2.c-l1.c)/(l1.a-l2.a); o.y=(l2.c+o.x*l2.a)/(-l2.b); return o;
	}
}
Tl getl(Tp x,double k){Tl l; l.a=k; l.b=-1; l.c=-x.x*k+x.y; return l;}
Tl getl(Tp a,Tp b){double k=(b.y-a.y)/(b.x-a.x); return getl(a,k);}
Tp getp(Tp x,Tp a,Tp b){Tl l1=getl(x,sk),l2=getl(a,b); return getp(l1,l2);}
bool check(Tp x,Tp a,Tp b){Tp o=getp(x,a,b); return o.x+eps>a.x && o.x-eps<b.x;}
double gety(Tp a,double x){
	Tl l=getl(a,sk); return (l.c+l.a*x)/(-l.b);
}
string a=""; char xxx[100],*tmp=xxx;
inline bool cmp(double *a,double *b){return *a<*b;}
void work(){
	for (int i=1;i<=n;++i) p[i]=h+i; sort(p+1,p+n+1,cmp);
	double ans=0; Tp last=e[1]; int now=1;
	for (int i=1;i<=n;++i){
		w[p[i]-h]=last; ans+=*p[i]; last.y+=*p[i]; int ln=now;
		while (now<m && !check(last,e[now],e[now+1])) ++now;
		if (now<m) last=getp(last,e[now],e[now+1]);
		else if (i<n){
			int tm=m;
			for (int x=ln+1;x<m;++x)
				if ((e[x].y-gety(last,e[x].x))>(e[tm].y-gety(last,e[tm].x))) tm=x;
			if (*p[n]-*p[i]>e[tm].y+*p[n]-gety(last,e[tm].x)){
				ans+=*p[n]-*p[i];
				for (++i;i<=n;++i) w[p[i]-h]=last;
			}else{
				ans+=e[tm].y+*p[n]-gety(last,e[tm].x);
				for (++i;i<=n;++i) w[p[i]-h]=e[tm];
			}
		}
	}
	printf("%.7f\n",ans);
	for (int i=1;i<=n;++i) printf("%.10f\n",w[i].x);
}
int main(){
	while (scanf("%d%d",&n,&m)!=EOF) init(),work();
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章