计算几何专项:UVa 10084

本文介绍了一种基于半平面交的算法实现,该算法通过计算两已知点的中垂线来确定切割方向,并利用多边形切割方法求解半平面交集。代码实现了根据输入的坐标和指示方向(Colder/Hotter/Same)动态更新并计算得到的多边形面积。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一道半平面交,切割线为2点的中垂线。然后根据colder、hotter来判断切割的方向。这里用切割多边形的方法求半平面交即可。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
using namespace std;
const double eps=1e-6;
int dcmp(double x)
{
    if(fabs(x)<eps) return 0;
    else return x<0?-1:1;
}
struct point
{
    double x,y;
    point(double x=0,double y=0):x(x),y(y){}
};
point operator-(point a,point b){return point(a.x-b.x,a.y-b.y);}
point operator+(point a,point b){return point(a.x+b.x,a.y+b.y);}
point operator*(point a,double p){return point(a.x*p,a.y*p);}
double cross(point a,point b){return a.x*b.y-a.y*b.x;}
double dot(point a,point b){return a.x*b.x+a.y*b.y;}
double area(vector<point> p)
{
    if(p.size()<=2) return 0;
    double ans=0;
    for(int i=1;i<p.size()-1;i++)
        ans+=cross(p[i]-p[0],p[i+1]-p[0]);
    return ans/2;
}
point getinter(point p,point v,point q,point w)
{
    point u=p-q;
    double t=cross(w,u)/cross(v,w);
    return p+v*t;
}
bool onseg(point p,point a1,point a2)
{
    return dcmp(cross(a1-p,a2-p))==0&&dcmp(dot(a1-p,a2-p))<0;
}
vector<point> cut(vector<point> poly,point a,point b,int flag)
{
    vector<point> newpoly;
    int n=poly.size();
    for(int i=0;i<n;i++)
    {
        point c=poly[i],d=poly[(i+1)%n];
        if(dcmp(cross(b-a,c-a))*flag>=0) newpoly.push_back(c);
        if(dcmp(cross(b-a,c-d)!=0))
        {
            point ip=getinter(a,b-a,c,d-c);
            if(onseg(ip,c,d)) newpoly.push_back(ip);
        }
    }
    return newpoly;
}
vector<point> p;
void init()
{
    p.clear();
    p.push_back(point(0,0));
    p.push_back(point(10,0));
    p.push_back(point(10,10));
    p.push_back(point(0,10));
}
point pre,cur;
char s[50];
char j[3][50]={"Colder","Hotter","Same"};
int main()
{
    init();
    pre.x=0;pre.y=0;
    while(scanf("%lf%lf%s",&cur.x,&cur.y,s)!=EOF)
    {
        int flag;
        point a=point((cur.x+pre.x)/2,(cur.y+pre.y)/2);
        point v=point(-(cur.y-pre.y),cur.x-pre.x);
        point b=a+v;
        if(strcmp(s,j[2])==0)
            p.clear();
        else if(strcmp(s,j[0])==0)
        {
            if(dcmp(cross(b-a,pre-a))>=0) flag=1;
            else flag=-1;
        }
        else
        {
            if(dcmp(cross(b-a,cur-a))>0) flag=1;
            else flag=-1;
        }
        p=cut(p,a,b,flag);
        pre.x=cur.x;pre.y=cur.y;
        printf("%.2f\n",area(p));
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值