| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
这么做/*
枚举左下角
然后f[i][j]用来表示以点i,点j为凸包最后两个点的最大面积
*/
#include<iostream>
using namespace std;
#define maxn 101
#define sqr(x) ((x)*(x))
#define Inf 1e30
inline int Cross_Product(int x_1,int y_1,int x_2,int y_2) {
return x_1*y_2-x_2*y_1;
}
struct Point {
int x,y;
void Readin() {
scanf("%d%d",&x,&y);
}
void Minus(Point s) {
x-=s.x,y-=s.y;
}
bool In(Point a,Point b) {
int r1=Cross_Product(-x,-y,a.x-x,a.y-y);
int r2=Cross_Product(a.x-x,a.y-y,b.x-x,b.y-y);
int r3=Cross_Product(b.x-x,b.y-y,-x,-y);
return (r1>0 && r2>0 && r3>0 || r1<0 && r2<0 && r3<0);
}
} p[maxn],q[maxn],s;
int n,m;
bool done[maxn][maxn];
double ans,rec[maxn][maxn];
int Compare_Horizontal(const void *a,const void *b) {
if (((Point*)a)->y==((Point*)b)->y) return ((Point*)a)->x-((Point*)b)->x;
return ((Point*)a)->y-((Point*)b)->y;
}
int Compare_Angle(const void *a,const void *b) {
int x_1=((Point*)a)->x,y_1=((Point*)a)->y;
int x_2=((Point*)b)->x,y_2=((Point*)b)->y;
int tmp=Cross_Product(x_1,y_1,x_2,y_2);
if (tmp) return -tmp;
return -( sqr(x_1)+sqr(y_1)-sqr(x_2)-sqr(y_2) );
}
void Init() { //读入并且排水平序
scanf("%d",&n);
for (int i=0; i<n; i++) p[i].Readin();
qsort(p,n,sizeof(Point),Compare_Horizontal);
ans=0.0;
}
double f(int i,int j) {
if (done[i][j]) return rec[i][j];
done[i][j]=true;
for (int k=i+1; k<j; k++) //判断状态是否合法
if (q[k].In(q[i],q[j])) {
rec[i][j]=-Inf;
return rec[i][j];
}
rec[i][j]=Cross_Product(q[i].x,q[i].y,q[j].x,q[j].y)*0.5; //向前转移
if (!Cross_Product(q[i].x,q[i].y,q[j].x,q[j].y) || Cross_Product(q[i].x,q[i].y,q[i+1].x,q[i+1].y)) {
double tmp=0.0;
for (int k=0; k<i; k++)
if (Cross_Product(q[i].x-q[j].x,q[i].y-q[j].y,q[k].x-q[i].x,q[k].y-q[i].y)<=0) tmp>?=f(k,i);
rec[i][j]+=tmp;
}
return rec[i][j];
}
void Dp() {
memset(done,0,sizeof(done));
memset(rec,0,sizeof(rec));
for (int i=0; i<m-1; i++)
for (int j=i+1; j<m; j++) ans>?=f(i,j);
}
void Work() { //枚举凸包的左下角
for (int i=0; i<n-2; i++) {
s=p[i];
m=n-1-i;
for (int j=0; j<m; j++) q[j]=p[j+i+1];
for (int j=0; j<m; j++) q[j].Minus(s); //把后面的点都拿出来,再排极角序
qsort(q,m,sizeof(Point),Compare_Angle);
Dp(); //动态规划
}
}
int main() {
int test;
for (scanf("%d",&test); test; test--) {
Init();
Work();
printf("%.1lf\n",ans);
}
return 0;
}
Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator