AOJ 2121 Castle Wall

来源:互联网 发布:互穿网络防腐涂料 编辑:程序博客网 时间:2024/04/30 00:17

有一个国王想将凹多边形的城堡变为凸多边形,需要毁掉一些墙造新的墙

造新墙的限制条件是:

1. 新墙只能连接原凹多边形的两个顶点。

2. 新墙总长度不超过r

已知所有顶点都在整数格点上,且在第一象限100*100正方形边上或内部。

求最大凸多边形城堡的面积


由于所有点都在整数格点上,所以任意整数格点多边形的面积*2后都是整数。

接下来扫出所有可以连接的边,dp面积即可


要注意由于面积*2了,而且都是有向面积,会有负数,所以最后数组要开到100*100*2*2=40000. 其中100*100是凸多边形的最大面积

接下来输出时除以2即可。



/*author: birdstorm*/#include <iostream>#include <cstdio>#include <cstring>#include <cctype>#include <cstdlib>#include <cmath>#include <vector>#include <queue>#include <stack>#include <map>#include <complex>#include <set>#include <algorithm>#include <climits>#include <cfloat>#define MAXN 100//#define N 105#define inf 1.0e20//#define eps 1.0e-8#define MOD 1000000007#define next(i) (i+1)%sz#define For(i,m,n) for(int i=(m);i<(n);i++)#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)#define rep(i,m,n) for(int i=(m);i<=(n);i++)#define repd(i,m,n) for(int i=(m);i>=(n);i--)#define LL long long#define testusing namespace std;const double eps=1.0e-8;const double pi=acos(-1.0);struct point{    double x,y;    point():x(0),y(0){}    point(double x,double y):x(x),y(y) {}    point operator + (const point &a) const{        return point(x+a.x,y+a.y);    }    point operator - (const point &a) const{        return point(x-a.x,y-a.y);    }    bool operator < (const point &a) const{        return x+eps<a.x || abs(x-a.x)<eps && y+eps<a.y;    }    bool operator == (const point &a) const{        return abs(x-a.x)<eps && abs(y-a.y)<eps;    }    point operator * (double c) const{        return point(c*x,c*y);    }    point operator / (double c) const{        return point(x/c,y/c);    }};typedef vector<point> polygon; //POLYGONinline double cross(point a,point b){    return a.x*b.y-a.y*b.x;}inline double mul(const point &a, const point &b){    return a.x*b.x+a.y*b.y;}int dlcmp(double x){return x<-eps?-1:x>eps;}struct line{    point a,b;    line(){}    line(const point &a,const point &b):a(a),b(b){}};bool intersect(const line &L1,const line &L2){return dlcmp(cross(L1.b-L1.a,L2.b-L1.a))*dlcmp(cross(L1.b-L1.a,L2.a-L1.a))<0&&dlcmp(cross(L1.a-L2.a,L2.b-L2.a))*dlcmp(cross(L1.b-L2.a,L2.b-L2.a))<0;}bool on_line(point a, point b, point c){    if(dlcmp(cross(a-b,a-c))) return false;    return dlcmp(mul(a-c,b-c))<0;}point p[MAXN];bool a[MAXN][MAXN];double x[MAXN], y[MAXN], dp[MAXN][40005];double dist[MAXN][MAXN];double r;int n;int main(){//    freopen("2121-input.txt","r",stdin);//    freopen("2121-output2.txt","w",stdout);    int cs=1;    while(scanf("%d%lf",&n,&r),n){        int s=0;        For(i,0,n){            scanf("%lf%lf",&x[i],&y[i]);            if(x[i]<x[s]) s=i;        }        rep(i,0,n){            p[i]=point(x[(i+s)%n],y[(i+s)%n]);        }        memset(a,0,sizeof a);        rep(i,0,n){            rep(j,0,n){                dist[i][j]=sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));            }        }        double Area;        For(i,0,n){            rep(j,i+2,n){                if(i==0&&j==n) continue;                For(k,0,n){                    if(k==i||k==j%n) continue;                    if(on_line(p[i],p[j],p[k])){                        goto illegal;                    }                }                For(k,0,n){                    if(intersect(line(p[i],p[j]),line(p[k],p[k+1]))){                        goto illegal;                    }                }                Area=cross(p[i],p[j]);                for(int k=j-1; k>=i; k--){                    Area+=cross(p[k+1],p[k]);                }                if(Area<=eps){                    goto illegal;                }                a[i][j]=true;                continue;                illegal:                    a[i][j]=false;            }        }        rep(i,0,n){            For(j,0,40001){                dp[i][j]=1.0e20;            }        }        dp[0][20000]=0.0;        For(i,0,n){            rep(j,0,40000){                if(dp[i][j]>=1.0e20) continue;                int S=floor(cross(p[i],p[i+1])+eps);                dp[i+1][j+S]=min(dp[i+1][j+S],dp[i][j]);                rep(k,i+2,n){                    if(a[i][k]){                        S=floor(cross(p[i],p[k])+eps);                        dp[k][j+S]=min(dp[k][j+S],dp[i][j]+dist[i][k]);                    }                }            }        }        int ret=0;        For(i,20000,40001){            if(dp[n][i]<=r) ret=i-20000;        }        printf("case %d: %.1f\n",cs++,(double)ret/2.0);    }    return 0;}


0 0
原创粉丝点击