//poj2540
//题目意思:
//在一个以(0,0)和(10.0,10.0)为对角线的矩形内有 一个目标点,
//一个玩家从(0,0)开始指定另一个点,另一个玩家宣布是靠近还是远去还是相同距离
//解题思路:
//1.对原来的点和所指定的点所成的线段求垂直平分线,(取中点和向量旋转可获得两点)
//2.根据指定的方向,再求形成的多边形(多边形的切割):
// (1).按一定顺序用一个数组来存下所需的点,同时还要判断是否加入 多边形与直线的交点
// (求交点时要注意直线是否与边重合了);
// (2).删除重复点;
//3.再求形成的多边形的面积:每相邻的两个顶点和原点形成三角形来计算(叉积)。
//4.保留多边形,返回步骤1。
//代码如下:
#include<iostream>
#include<cstdio>
#include<math.h>
#include<string.h>
#define eps 1e-8
//#define zero(x) (((x) >0 ? (x) : (-x))<eps)
struct Point{double x,y;};
struct tLine{Point s,e;};//两点成线
double xmult(Point p1,Point p2,Point p0)
{
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
bool zero(double x)
{
return (x>0.0 ? x : -x)<eps;
}
//求垂直平分线
tLine veDiLine(Point p1,Point p2)
{
tLine tl;
tl.s.x=(p1.x+p2.x)*0.5;
tl.s.y=(p1.y+p2.y)*0.5;
Point p;
p.x=p1.x-tl.s.x;
p.y=p1.y-tl.s.y;
tl.e.x=tl.s.x-p.y;
tl.e.y=tl.s.y+p.x;
return tl;
}
//判断p1,p2两点是否在l直线的同侧
int same_side(Point p1,Point p2,Point l1,Point l2)
{
return xmult(l1,p1,l2)*xmult(l1,p2,l2)>eps;
}
Point intersection(Point p1,Point p2,Point p3,Point p4)
{
Point ret=p1;
double t=((p1.x-p3.x)*(p3.y-p4.y)-(p3.x-p4.x)*(p1.y-p3.y))
/((p1.x-p2.x)*(p3.y-p4.y)-(p3.x-p4.x)*(p1.y-p2.y));
ret.x+=t*(p2.x-p1.x);
ret.y+=t*(p2.y-p1.y);
return ret;
}
//多边形切割,保证side不在线上
void polygon_cut(int &n,Point *p,Point l1,Point l2,Point side)
{
Point pp[1000];
int m=0,i;
for(i=0;i<n;i++)
{
if(same_side(p[i],side,l1,l2))
pp[m++]=p[i];
if(!same_side(p[i],p[(i+1)%n],l1,l2)
&&!(zero(xmult(p[i],l1,l2))
&&zero(xmult(p[(i+1)%n],l1,l2))))
pp[m++]=intersection(p[i],p[(i+1)%n],l1,l2);
}
n=0;
for(i=0;i<m;i++)
if(!i||!zero(pp[i].x-pp[i-1].x)||!zero(pp[i].y-pp[i-1].y))
p[n++]=pp[i];
if(zero(p[n-1].x-p[0].x)&&zero(p[n-1].y-p[0].y))
n--;//这个容易忽略,切记
if(n<3)
n=0;
}
//求多边形的面积
double area_of_polygon(int n,Point *p)
{
int i;
double s=0;
if(n<3)return 0;
for(i=0;i<n;i++)
s+=p[(i+1)%n].y*(p[i].x-p[(i+2)%n].x);
return fabs(s)/2.0;//若s为正值
}
Point pol[10000];
int n;
int main()
{
Point p,next;
char str[20];
double s=100.0;
p.x=0.0;
p.y=0.0;
pol[0].x=0.0;
pol[0].y=0.0;
pol[1].x=10.0;
pol[1].y=0.0;
pol[2].x=10.0;
pol[2].y=10.0;
pol[3].x=0.0;
pol[3].y=10.0;
n=4;
bool flag=true;
while(~scanf("%lf %lf %s",&next.x,&next.y,str))
{
tLine tl;
Point side;//) &&
if(str[0]=='S'||!flag
||(zero(p.x-next.x)&&zero(p.y-next.y)))
{
n=0;
s=0.0;
printf("0.00\n");
flag=false;
continue;
}
if(str[0]=='H')
{
tl=veDiLine(p,next);
p.x=next.x;
p.y=next.y;
}
else if(str[0]=='C')
{
tl=veDiLine(p,next);
}
if(s>eps)
{
polygon_cut(n,pol,tl.s,tl.e,p);
s=area_of_polygon(n,pol);
}
printf("%.2lf\n",s);
p.x=next.x;
p.y=next.y;
}
return 0;
}
分享到:
相关推荐
计算几何半平面交,poj2451 一题是模版题,这里的代码可以作为模版使用,速度比较快
该资源详细的介绍了acm中的半平面交,你可以通过学习这个,加上poj上的习题练习,则完全掌握半平面交,对你搞acm有很大帮助
POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类
poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题...
poj1379 给予平面内一个点集; 使用模拟退火求出一个点使该点到上述点集内任意一点最短距离最长。
poj分类poj分类poj分类poj分类
POJ第1861题源码 POJ第1861题源码 POJ第1861题源码
北大POJ1159-Palindrome 解题报告+AC代码
poj 3414解题报告poj 3414解题报告poj 3414解题报告poj 3414解题报告
poj 1012解题报告poj 1012解题报告poj 1012解题报告poj 1012解题报告
poj 2329解题报告poj 2329解题报告poj 2329解题报告poj 2329解题报告
poj 1659解题报告poj 1659解题报告poj 1659解题报告poj 1659解题报告
C语言 poj npu 西工大 C语言Poj答案全完整打包,给有需要的朋友
poj 百练 题目分类 poj 百练 题目分类
POJ1083的代码,POJ1083的代码,POJ1083的代码
POJ1503解答 POJ1503解答,正确答案(已通过POJ)
POJ1048,加强版的约瑟夫问题 难度中等
北大POJ2002-Squares 解题报告+AC代码
poj 1001答案
POJ2968代码有用,欢迎下载,POJ代码