Nice Milk
問題文
UVa
http://uva.onlinejudge.org/external/101/10117.html
POJ
http://poj.org/problem?id=1271
高さhの牛乳に凸多角形のパンをk回浸す。
牛乳に浸されたパンの面積の最大値を求めよ。
パンの辺との距離がhかつ辺に平行な直線でパンを切り取る。
これをmin(n,k)回繰り返して残るパンの面積の最小値を求める。
(元のパンの面積)-(残ったパンの面積の最小値)を出力する。
↓のコードはUVaでは通ったけどPOJではTLE食らってる。
#include<cmath> #include<algorithm> #include<iostream> #include<vector> #include<climits> #include<cfloat> #include<cstdio> #define curr(P, i) P[(i) % P.size()] #define next(P, i) P[(i+1) % P.size()] #define Line pair<point,point> using namespace std; double EPS = 1e-10; double PI=3.1415926535; double add(double a, double b){ if(abs(a+b) < EPS * (abs(a)+abs(b)))return 0; return a+b; } struct point{ double x, y; point(){} point(double x,double y) : x(x) , y(y){} point operator + (point p){ return point(add(x,p.x), add(y,p.y)); } point operator - (point p){ return point(add(x,-p.x), add(y,-p.y)); } point operator * (double d){ return point(x*d,y*d); } }; double dot(point a, point b) { return (a.x * b.x + a.y * b.y); } double cross(point a, point b) { return (a.x * b.y - a.y * b.x); } double norm(point a){ return sqrt(a.x*a.x+a.y*a.y); } int ccw(point a, point b, point c) { b = b-a; c = c-a; if (cross(b, c) > 0) return +1; if (cross(b, c) < 0) return -1; if (dot(b, c) < 0) return +2; if (norm(b) < norm(c)) return -2; return 0; } point intersection_l(point a1, point a2, point b1, point b2) { return a1 + (a2 - a1) * (cross(b2 - b1,b1 - a1) / cross(b2 - b1,a2 - a1)); } vector<point> convex_cut(vector<point>pol,point a,point b){ vector<point>q; for (int i=0; i<pol.size();i++) { point A=curr(pol,i),B=next(pol, i); if (ccw(a,b,A)!=-1)q.push_back(A); if (ccw(a,b,A)*ccw(a,b,B)<0) q.push_back(intersection_l(A,B,a,b)); } return q; } double areaPol(vector<point> t){ double area=0; for(int i=0;i<t.size();i++) area+=(curr(t,i).x-next(t,i).x)*(curr(t,i).y+next(t,i).y); return abs(area)/2.0; } point symmetry(point p1, point p2, point Q){ double xa,ya,xb,yb,t1,t2; point R; xa=Q.x-p1.x,ya=Q.y-p1.y; xb=p2.x-p1.x,yb=p2.y-p1.y; t1=xa*xb+ya*yb,t2=xb*xb+yb*yb; R.x=2*(p1.x+xb*t1/t2)-Q.x; R.y=2*(p1.y+yb*t1/t2)-Q.y; return R; } Line parallel_line(point a,point b,double h){ double t = atan((a.y-b.y)/(a.x-b.x)); point a_(a.x + h*cos(t+PI/2), a.y + h*sin(t+PI/2)); point b_(b.x + h*cos(t+PI/2), b.y + h*sin(t+PI/2)); if(ccw(a,b,a_)==-1)a_=symmetry(a,b,a_),b_=symmetry(a,b,b_); return make_pair(a_,b_); } int n; double h; vector<Line>L; double func(int k,int j,vector<point> pol){ if(k==0 || j==n)return areaPol(pol); double res=DBL_MAX; for(int i=j;i<n;i++) res=min(res,func(k-1,i+1,convex_cut(pol,L[i].first,L[i].second))); return res; } int main(void){ int k; while(cin >> n >> k >> h,n|k){ vector<point>pol(n); L.clear(); for(int i=0;i<n;i++) cin >> pol[i].x >> pol[i].y; for(int i=0;i<n;i++) L.push_back(parallel_line(curr(pol,i),next(pol,i),h)); printf("%.2f\n",areaPol(pol)-func(min(n,k),0,pol)); } return 0; }