题意:有一个长 1 的正方形框(放在x-y坐标系的0-1上),然后给出一个数 n 代表该正方形每条边上的钉子数,接下来给出这钉子的坐标(按顺序且钉子没有重合的情况),把对边上的点依次按顺序用线连接起来,得到一张不规则的网,由多个不过则四边形构成,输出这些小四边形中面积最大一块的面积。
思路很简单,计算出焦点的坐标,用矩阵存储点的坐标值,然后2重循环扫描下矩阵就Ok了,估计因为题目太长,还有计算几何太繁琐,整个 ZOJ 就80+人次提交,过了50+,唉,计算几何啊,伤不起啊……
代码:
#include<stdio.h>
#include<math.h>
#include<string.h>
#define N 35
int n;
double area[N][N];
struct point{
double x,y;
};
point mat[N][N];
struct Line
{
double a,b,c;
};
double xmult(point a,point b,point c){
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}
Line getline(point p1,point p2){
Line tmp;
tmp.a=p1.y-p2.y;
tmp.b=p2.x-p1.x;
tmp.c=p1.x*p2.y-p2.x*p1.y;
return tmp;
}
point fun_point(int i,int j){
//求点mat[i][1],mat[i][n+2]所成直线,和mat[1][j],mat[n+2][j]直线的交点
//本题条件特殊,每两条线一定跨立相交,所以直接用方程求解即可,a*x+b*y+c=0
point tmp;
//l1 (mat[i][1],mat[i][n+2])
Line l1=getline(mat[i][1],mat[i][n+2]);
//l2 (mat[1][j],mat[n+2][j])
Line l2=getline(mat[1][j],mat[n+2][j]);
tmp.x=(l1.b*l2.c-l2.b*l1.c)/(l1.a*l2.b-l2.a*l1.b);
tmp.y=(l1.c*l2.a-l2.c*l1.a)/(l1.a*l2.b-l2.a*l1.b);
return tmp;
}
void getmat(){
int i,j;
memset(mat,0,sizeof(mat));
//a
//for(i=1;i<=n+2;i++) mat[n+2][i].y=0.0;
for(i=1;i<=n;i++)
scanf("%lf",&mat[n+2][i+1].x);
//b
for(i=1;i<=n+2;i++) mat[1][i].y=1.0;
for(i=1;i<=n;i++)
scanf("%lf",&mat[1][i+1].x);
//c
//for(i=1;i<=n+2;i++) mat[i][1].x=0.0;
for(i=n+1;i>1;i--)
scanf("%lf",&mat[i][1].y);
//d
for(i=1;i<=n+2;i++) mat[i][n+2].x=1.0;
for(i=n+1;i>1;i--)
scanf("%lf",&mat[i][n+2].y);
for(i=2;i<n+2;i++)
{
for(j=2;j<n+2;j++)
mat[i][j]=fun_point(i,j);
}
}
double get_area(int i,int j) //求四边形面积
{
double s1=0.0,s2=0.0,s=0.0;
s1=xmult(mat[i][j],mat[i][j+1],mat[i+1][j+1]);
s2=xmult(mat[i][j],mat[i+1][j],mat[i+1][j+1]);
s=( fabs(s1)+fabs(s2) )/2.0;
return s;
}
int main()
{
int i,j;
while(scanf("%d",&n),n)
{
getmat();
double max=0.0;
for(i=1;i<n+2;i++)
{
for(j=1;j<n+2;j++)
{
area[i][j]=get_area(i,j);
if(area[i][j]>max)max=area[i][j];
}
}
printf("%lf\n",max);
}
return 0;
}