poj1408

题目不难,大致题意为:

给定一个单位矩阵,并在每条边上面“嵌入”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;
}
	


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值