有一个国王想将凹多边形的城堡变为凸多边形,需要毁掉一些墙造新的墙
造新墙的限制条件是:
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 test
using 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; //POLYGON
inline 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;
}