ZOJ 1683 Fishnet (POJ 1408)(计算线段交点&叉积求面积)

题意:有一个长 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;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值