纠结了一下午啊!!!超时啊!!!我用WS的方法测了好久又测了下我的时间复杂度!!!感觉应该就卡在数据的最后一组啊!!!!
在UVA wa了啊!!!说明UVA 机器比POJ快啊!!!
思路:求蘸牛奶的最大面积,也就是半平面交后中间区域最小,所以只需要求得半平面交中间的最小区域即可。这个实现需要DFS枚举哈。
一直TLE,后来看网上的还是不知道从哪入手。后来想起一种优化方法,因为里面的边是平行的,所以如果选择里面的边,那么外面的那个边就不需要了(因为会在排序后删掉的),那么直接覆盖那条边就行了,还省点时间。这么一弄,居然WA了 = = 后来发现个很2的错误,输入放在输出前了 T T 。。。输出0.00后直接continue了 = = 改掉后AC。
两个代码都是DFS的差异,一个是查找到一条边就加入然后到k条后求面积。另一种是把DFS方案全部列出来,然后再纠结 = =。。。
第一种快点,因为如果找到面积为0的我就直接return了。而且,如果剩下可选的元素比需要选的元素个数少,也return了。不过最少还600+MS.。。。T T.。。
P.S. 我怀疑过unique的删除,因为如果用半平面交的话,第一次删除斜率相等的点的话,应该留下最左边的(我定义最左边为有效方向)。那么我怕unique乱删。不过刚才测试了下,unique删的都是第一个元素,那么我就放心了。
P.S. 刚查了下unique的内部实现,确实是保留第一个元素,呵呵。
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <stack>
#include <climits>
using namespace std;
const int MAX = 25;
const double inf = 1e20;
struct point {double x,y;};
struct line { double ang; point a,b;};
point p[MAX],s[MAX];
line ln[MAX],deq[MAX],ltmp[MAX],ll[MAX],lk[MAX];;
double h,mmin;
const double eps = 1e-6;
int k;
bool dy(double x,double y) { return x > y + eps;} // x > y
bool xy(double x,double y) { return x < y - eps;} // x < y
bool dyd(double x,double y) { return x > y - eps;} // x >= y
bool xyd(double x,double y) { return x < y + eps;} // x <= y
bool dd(double x,double y) { return fabs( x - y ) < eps;} // x == y
double disp2p(point a,point b) // a b 两点之间的距离
{
return sqrt( ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ) );
}
double crossProduct(point a,point b,point c)//向量 ac 在 ab 的方向
{
return (c.x - a.x)*(b.y - a.y) - (b.x - a.x)*(c.y - a.y);
}
void changepoint(point a,point b,point &c,point &d)
{
double len = disp2p(a,b);
double dx = h / len * ( a.y - b.y );
double dy = h / len * (-a.x + b.x );
c.x = a.x + dx; c.y = a.y + dy;
d.x = b.x + dx; d.y = b.y + dy;
}
void makeline_hp(point a,point b,line &l) // 线段(向量ab)右侧区域有效
{
l.a = a; l.b = b;
l.ang = atan2(a.y - b.y,a.x - b.x); // 如果是左侧区域,改成b.y - a.y,b.x - a.x
}
bool equal_ang(line a,line b) // 第一次unique的比较函数
{
return dd(a.ang,b.ang);
}
bool cmphp(line a,line b) // 排序的比较函数
{
if( dd(a.ang,b.ang) ) return xy(crossProduct(b.a,b.b,a.a),0.0);
return xy(a.ang,b.ang);
}
bool equal_p(point a,point b)//第二次unique的比较函数
{
return dd(a.x,b.x) && dd(a.y,b.y);
}
bool parallel(line u,line v)
{
return dd( (u.a.x - u.b.x)*(v.a.y - v.b.y) - (v.a.x - v.b.x)*(u.a.y - u.b.y) , 0.0 );
}
point l2l_inst_p(line l1,line l2)
{
point ans = l1.a;
double t = ((l1.a.x - l2.a.x)*(l2.a.y - l2.b.y) - (l1.a.y - l2.a.y)*(l2.a.x - l2.b.x))/
((l1.a.x - l1.b.x)*(l2.a.y - l2.b.y) - (l1.a.y - l1.b.y)*(l2.a.x - l2.b.x));
ans.x += (l1.b.x - l1.a.x)*t;
ans.y += (l1.b.y - l1.a.y)*t;
return ans;
}
double area_polygon(point p[],int n)
{
double s = 0.0;
for(int i=0; i<n; i++)
s += p[(i+1)%n].y * p[i].x - p[(i+1)%n].x * p[i].y;
return fabs(s)/2.0;
}
void inst_hp_nlogn(line *ln,int n,point *s,int &len)
{
len = 0;
sort(ln,ln+n,cmphp);
n = unique(ln,ln+n,equal_ang) - ln;
int bot = 0,top = 1;
deq[0] = ln[0]; deq[1] = ln[1];
for(int i=2; i<n; i++)
{
if( parallel(deq[top],deq[top-1]) || parallel(deq[bot],deq[bot+1]) )
return ;
while( bot < top && dy(crossProduct(ln[i].a,ln[i].b,
l2l_inst_p(deq[top],deq[top-1])),0.0) )
top--;
while( bot < top && dy(crossProduct(ln[i].a,ln[i].b,
l2l_inst_p(deq[bot],deq[bot+1])),0.0) )
bot++;
deq[++top] = ln[i];
}
while( bot < top && dy(crossProduct(deq[bot].a,deq[bot].b,
l2l_inst_p(deq[top],deq[top-1])),0.0) ) top--;
while( bot < top && dy(crossProduct(deq[top].a,deq[top].b,
l2l_inst_p(deq[bot],deq[bot+1])),0.0) ) bot++;
if( top <= bot + 1 ) return ;
for(int i=bot; i<top; i++)
s[len++] = l2l_inst_p(deq[i],deq[i+1]);
if( bot < top + 1 ) s[len++] = l2l_inst_p(deq[bot],deq[top]);
len = unique(s,s+len,equal_p) - s;
}
void DFS(int x,int n,int sum)
{
if( mmin == 0.0 ) return ;
if( n - x < k - sum ) return ;
if( sum == k )
{
int len;
memcpy(ltmp,ln,sizeof(ln));
inst_hp_nlogn(ltmp,n,s,len);
mmin = min(mmin,area_polygon(s,len));
if( mmin == 0.0 ) return ;
return ;
}
for(int i=x; i<n; i++)
{
ln[i] = ll[i];
DFS(i+1,n,sum+1);
if( mmin == 0.0 ) return ;
ln[i] = lk[i];
}
}
int main()
{
int n;
while( ~scanf("%d%d%lf",&n,&k,&h) )
{
if( !(n || k || h) ) break;
for(int i=0; i<n; i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
if( h == 0 || k == 0 )
{
printf("0.00\n");
continue;
}
p[n] = p[0];
double area = area_polygon(p,n);
for(int i=0; i<n; i++)
{
point c,d;
changepoint(p[i],p[i+1],c,d);
makeline_hp(c,d,ll[i]);
makeline_hp(p[i],p[i+1],ln[i]);
}
memcpy(lk,ln,sizeof(ln));
if( k > n ) k = n;
mmin = inf;
DFS(0,n,0);
double ans = area - mmin;
printf("%.2lf\n",ans);
}
return 0;
}
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <stack>
#include <climits>
using namespace std;
const int MAX = 25;
const double inf = 1e20;
const double pi = acos(-1.0);
struct point {double x,y;};
struct line { double ang; point a,b;};
point p[MAX],s[MAX];
line ln[MAX],deq[MAX],ltmp[MAX],ll[MAX];
double h,mmin;
const double eps = 1e-6;
int k,cnt;
bool dy(double x,double y) { return x > y + eps;} // x > y
bool xy(double x,double y) { return x < y - eps;} // x < y
bool dyd(double x,double y) { return x > y - eps;} // x >= y
bool xyd(double x,double y) { return x < y + eps;} // x <= y
bool dd(double x,double y) { return fabs( x - y ) < eps;} // x == y
double disp2p(point a,point b) // a b 两点之间的距离
{
return sqrt( ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ) );
}
double crossProduct(point a,point b,point c)//向量 ac 在 ab 的方向
{
return (c.x - a.x)*(b.y - a.y) - (b.x - a.x)*(c.y - a.y);
}
void changepoint(point a,point b,point &c,point &d)
{
double len = disp2p(a,b);
double dx = h / len * ( a.y - b.y );
double dy = h / len * (-a.x + b.x );
c.x = a.x + dx; c.y = a.y + dy;
d.x = b.x + dx; d.y = b.y + dy;
}
void makeline_hp(point a,point b,line &l)
{
l.a = a; l.b = b;
l.ang = atan2(a.y - b.y,a.x - b.x);
}
bool equal_ang(line a,line b) // 第一次unique的比较函数
{
return dd(a.ang,b.ang);
}
bool cmphp(line a,line b) // 排序的比较函数
{
if( dd(a.ang,b.ang) ) return xy(crossProduct(b.a,b.b,a.a),0.0);
return xy(a.ang,b.ang);
}
bool equal_p(point a,point b)//第二次unique的比较函数
{
return dd(a.x,b.x) && dd(a.y,b.y);
}
bool parallel(line u,line v)
{
return dd( (u.a.x - u.b.x)*(v.a.y - v.b.y) - (v.a.x - v.b.x)*(u.a.y - u.b.y) , 0.0 );
}
point l2l_inst_p(line l1,line l2)
{
point ans = l1.a;
double t = ((l1.a.x - l2.a.x)*(l2.a.y - l2.b.y) - (l1.a.y - l2.a.y)*(l2.a.x - l2.b.x))/
((l1.a.x - l1.b.x)*(l2.a.y - l2.b.y) - (l1.a.y - l1.b.y)*(l2.a.x - l2.b.x));
ans.x += (l1.b.x - l1.a.x)*t;
ans.y += (l1.b.y - l1.a.y)*t;
return ans;
}
double area_polygon(point p[],int n)
{
if( n < 3 ) return 0.0;
double s = 0.0;
for(int i=0; i<n; i++)
s += p[(i+1)%n].y * p[i].x - p[(i+1)%n].x * p[i].y;
return fabs(s)/2.0;
}
line lk[MAX];
void inst_hp_nlogn(line *ln,int n,point *s,int &len)
{
len = 0;
sort(ln,ln+n,cmphp);
n = unique(ln,ln+n,equal_ang) - ln;
int bot = 0,top = 1;
deq[0] = ln[0]; deq[1] = ln[1];
for(int i=2; i<n; i++)
{
if( parallel(deq[top],deq[top-1]) || parallel(deq[bot],deq[bot+1]) )
return ;
while( bot < top && dy(crossProduct(ln[i].a,ln[i].b,
l2l_inst_p(deq[top],deq[top-1])),0.0) )
top--;
while( bot < top && dy(crossProduct(ln[i].a,ln[i].b,
l2l_inst_p(deq[bot],deq[bot+1])),0.0) )
bot++;
deq[++top] = ln[i];
}
while( bot < top && dy(crossProduct(deq[bot].a,deq[bot].b,
l2l_inst_p(deq[top],deq[top-1])),0.0) ) top--;
while( bot < top && dy(crossProduct(deq[top].a,deq[top].b,
l2l_inst_p(deq[bot],deq[bot+1])),0.0) ) bot++;
if( top <= bot + 1 ) return ;
for(int i=bot; i<top; i++)
s[len++] = l2l_inst_p(deq[i],deq[i+1]);
if( bot < top + 1 ) s[len++] = l2l_inst_p(deq[bot],deq[top]);
len = unique(s,s+len,equal_p) - s;
}
int t[150000][10];
int tt[10];
void DFS(int x,int n,int sum)
{
if( n - x < k - sum ) return ;
if( sum == k )
{
memcpy(t[cnt++],tt,sizeof(tt));
return ;
}
for(int i=x; i<n; i++)
{
tt[sum] = i;
DFS(i+1,n,sum+1);
}
}
int main()
{
int n,len;
point c,d;
while( ~scanf("%d%d%lf",&n,&k,&h) )
{
if( !(n || k || h) ) break;
cnt = 0;
for(int i=0; i<n; i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
if( h == 0 || k == 0 )
{
printf("0.00\n");
continue;
}
p[n] = p[0];
double area = area_polygon(p,n);
for(int i=0; i<n; i++)
{
changepoint(p[i],p[i+1],c,d);
makeline_hp(c,d,ll[i]);
makeline_hp(p[i],p[i+1],ln[i]);
}
if( k > n ) k = n;
mmin = inf;
DFS(0,n,0);
for(int i=0; i<cnt; i++)
{
memcpy(ltmp,ln,sizeof(ln));
for(int j=0; j<k; j++)
ltmp[t[i][j]] = ll[t[i][j]];
inst_hp_nlogn(ltmp,n,s,len);
mmin = min(mmin,area_polygon(s,len));
if( mmin == 0 )
break;
}
double ans = area - mmin;
printf("%.2lf\n",ans);
}
return 0;
}