题目不难,大致题意为:
给定一个单位矩阵,并在每条边上面“嵌入”n个点,这样每条边共有n+2个点。将单位矩阵对面相应位置的点连接起来,构成n*n个不规则四边形。要求出这n*n个矩阵中面积的最大值。
简单的模拟+叉积求三角形面积+不规则四边形划分成三角形求面积。
枚举每个四边形,将每个四边形划分为2个三角形。利用三角形求面积公式计算面积。比较求出最大面积。
那么关键点在于如何求三角形面积。
下面提供2中方法:
1)解析几何:
海伦公式: S=p*(p-a)*(p-b)*(p-c)取根号,其中p=(a+b+c)/2;
2)计算几何方法
S=1/2*| ac向量 叉乘 ab向量|
显然,计算几何方法更快,且精度更高(没有根号),代码也少,而且在求线段交点的过程中也会用到叉乘。一举两得
另外在模拟的过程中,要格外小心,因为很多细节要注意。
下面是代码 : 180K+0MS
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define Max 40
//#define eps 1e-7
#define Inf 999999.0 //取极大值,也可更大
typedef struct Point{ // 定义点结构
double x;
double y;
}point;
point node[Max][Max]; // 点矩阵
int n;
double det(double x1,double y1,double x2,double y2){ // 计算(x1,y1)叉乘(x2,y2)
return x1*y2-x2*y1;
}
double cross(point A,point B,point P){ // 计算向量AB与向量AP叉乘
return det(B.x-A.x,B.y-A.y,P.x-A.x,P.y-A.y);
}
void intersection(point A,point B,point C,point D,double &x,double &y){ // 计算AB线段与CD线段的交点
double area1=cross(A,B,C);
double area2=cross(A,B,D);
x=(area2*C.x-area1*D.x)/(area2-area1); // 横坐标
y=(area2*C.y-area1*D.y)/(area2-area1); // 纵坐标
return ;
}
int main(){
while(scanf("%d",&n),n){ //模拟过程
node[1][1].x=0.0,node[1][1].y=1.0;
node[1][n+2].x=1.0,node[1][n+2].y=1.0;
node[n+2][1].x=0.0,node[n+2][1].y=0.0;
node[n+2][n+2].x=1.0,node[n+2][n+2].y=0.0;
int i,j;
for(i=2;i<=n+1;i++){ //注意顺序
scanf("%lf",&node[n+2][i].x);
node[n+2][i].y=0.0;
}
for(i=2;i<=n+1;i++){
scanf("%lf",&node[1][i].x);
node[1][i].y=1.0;
}
for(i=n+1;i>=2;i--){ //注意顺序
scanf("%lf",&node[i][1].y);
node[i][1].x=0.0;
}
for(i=n+1;i>=2;i--){
scanf("%lf",&node[i][n+2].y);
node[i][n+2].x=1.0;
}
for(i=2;i<=n+1;i++)
for(j=2;j<=n+1;j++) // 至此,顶点矩阵模拟求出
intersection(node[i][1],node[i][n+2],node[1][j],node[n+2][j],node[i][j].x,node[i][j].y);
double max_area=-Inf; //计算n*n个四边形中面积的最大值
for(i=1;i<=n+1;i++)
for(j=1;j<=n+1;j++){
double temp=fabs(cross(node[i][j],node[i][j+1],node[i+1][j]))*0.5 //分解成两个三角形,叉乘求面积
+fabs(cross(node[i+1][j+1],node[i][j+1],node[i+1][j]))*0.5;
if(max_area<temp) //求最大值
max_area=temp;
}
printf("%.6lf\n",max_area); // 输出最大值
}
return 0;
}