ECNA 2018 D pizzacutting

题目大意:有些脑子缺根筋的人非要把蛋糕沿着水平和竖直的方向切,这会导致切出来的有些块很小没有卵用。定义面积与最大的比值小于p的为没有卵用的块,问切出来有多少个这样的块。输入r, dx, dy, x, y, p,代表半径、每次切的间隔、其中一个交点坐标。输入均为整数,r<=3000, dx,dy,x,y<=10000。

这个数据范围r<=3000,时限又长,所以暴力枚举矩形套圆和多边形交计算集合板子没问题。注意稍微优化一下,枚举矩形的起点和终点不超过圆的半径,否则会t。四个点在圆里面也没必要再算了。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. typedef double db;
  5. const db PI=acos(-1),eps=1e-8;
  6.  
  7. bool eq(db x){return fabs(x)<eps;}
  8. int sgn(db x){if (x<-eps) return -1; return x>eps;}
  9.  
  10. #define Vec const vec &
  11. #define Point const point &
  12. struct vec{
  13. 	db x,y;
  14. 	vec():x(0),y(0){}
  15. 	vec(db x, db y):x(x),y(y){}
  16. 	vec operator+(Vec v) const{return vec(x+v.x,y+v.y);}
  17. 	vec operator-(Vec v) const{return vec(x-v.x,y-v.y);}
  18. 	vec operator*(db a) const{return vec(x*a,y*a);}
  19. 	vec operator/(db a) const{return vec(x/a,y/a);}
  20.  
  21. 	db operator|(Vec v) const{return x*v.x+y*v.y;}
  22. 	db operator&(Vec v) const{return x*v.y-y*v.x;}
  23. 	db operator!() const{return sqrt(x*x+y*y);}
  24. };
  25. typedef vec point;
  26. db angle(Vec a, Vec b){return fabs(atan2(a&b,a|b));}
  27. db cross(Vec a, Vec b, Vec c){return b-a&c-a;}
  28. struct circle{
  29. 	point c; db r;
  30. };
  31. int segInt(Vec a, Vec b, circle c, point *ans){
  32. 	vec v=b-a, u=a-c.c;
  33. 	db e=v|v, f=v|u*2, g=(u|u)-c.r*c.r;
  34. 	db delta=f*f-4*e*g;
  35. 	if(delta<0) return 0;
  36. 	if (eq(delta)){
  37. 		db t=f/2/e;
  38. 		if (sgn(t)>=0 && sgn(t-1)<=0) return ans[0]=a-v*t,1;
  39. 		return 0;
  40. 	}
  41. 	db t1=(-f-sqrt(delta))/(2*e);
  42. 	db t2=(-f+sqrt(delta))/(2*e);
  43. 	point a1=a+v*t1, a2=a+v*t2;
  44. 	int cnt=0;
  45. 	if (sgn(t1)>=0 && sgn(t1-1)<=0) ans[cnt++]=a1;
  46. 	if (sgn(t2)>=0 && sgn(t2-1)<=0) ans[cnt++]=a2;
  47. 	return cnt;
  48. }
  49.  
  50. db secarea(Vec a, Vec b, db r){return r*r*angle(a,b)/2;}
  51. db triarea(Vec a, Vec b){return fabs(a&b)/2;}
  52.  
  53. db tri_cirarea(vec p1,vec p2, circle c){
  54. 	db r=c.r;
  55. 	p1=p1-c.c; p2=p2-c.c;
  56. 	c.c=vec(0,0);
  57. 	point p[2];
  58. 	if (sgn(!p1-r)<0){
  59. 		if (sgn(!p2-r)<0) return triarea(p1, p2);
  60. 		segInt(p1,p2,c,p);
  61. 		return triarea(p1,p[0])+secarea(p[0],p2,r);
  62. 	}
  63. 	if (sgn(!p2-r)<0){
  64. 		segInt(p1,p2,c,p);
  65. 		return secarea(p1,p[0],r)+triarea(p[0],p2);
  66. 	}
  67. 	int pc=segInt(p1,p2,c,p);
  68. 	if (pc==2) return secarea(p1,p[0],r)+triarea(p[0],p[1])+secarea(p[1],p2,r);
  69. 	return secarea(p1,p2,r);
  70. }
  71.  
  72. db poly_cirarea(point *p, int n, circle c){
  73. 	db ans=0;
  74. 	for (int i=0;i<n;i++){
  75. 		db d=sgn(cross(c.c,p[i],p[(i+1)%n]));
  76. 		ans+=d*tri_cirarea(p[i],p[(i+1)%n],c);
  77. 	}
  78. 	return fabs(ans);
  79. }
  80.  
  81. db ar[10000000]; int arc;
  82.  
  83. int main(){
  84. 	db x,y,dx,dy,r,p;
  85. 	while (cin>>r>>dx>>dy>>x>>y>>p){
  86. 		int ans=0;db maxa=0;
  87. 		for(;x<0;x+=dx);
  88. 		for(;y<0;y+=dy);
  89. 		for(;x>-r;x-=dx);
  90. 		for(;y>-r;y-=dy);
  91. 		for (db i=x;i<r;i+=dx)
  92. 			for (db j=y;j<r;j+=dy){
  93. 				point p[4]={vec(i,j),vec(i+dx,j),vec(i+dx,j+dy),vec(i,j+dy)};
  94. 				db a;
  95. 				if (!p[0]<r && !p[1]<r && !p[2]<r && !p[3]<r) a=dx*dy;
  96. 				else a=poly_cirarea(p,4,(circle){vec(0,0),r});
  97. 				if (a>eps) ar[arc++]=a; maxa=max(a,maxa);	
  98. 			}
  99. 		for (int i=0;i<arc;i++) {if(ar[i]/maxa<p+1e-6) ans++;}
  100. 		cout<<ans<<'\n';
  101. 	}
  102. 	return 0;
  103. }

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注