POJ 2540 Hotter Colder 半平面交 求可行域面积

 

题意:

有一个二维(0,0)到(10,10)的区域,一个人从(0,0)开始一次拜访区域内的点,去找一样东西(就在这个区域内),每次他到达一个新的点后,都会有一句话,来告诉你是离那个东西更近了(Hotter),还是更远了(Colder),或者距离不变(Same),然后让你算出,这时那个东西可能处在的位置的区域的面积

 

注意点:

 

1. 这题主要搞清楚半平面要取到的区域,还有中垂线自己YY。

小知识: 与直线ax+by+c=0垂直的直线方程为bx-ay+d = 0, 根据这个不用考虑斜率为0或不存在的问题,很方便。

2. same以后的值都为0;

其它 模板。

 

模板1:

View Code
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define eps 1e-8
#define inf 1<<29

struct point
{
    double x, y;
    point(){}
    point(double xx, double yy): x(xx), y(yy) {}
}p[110], tp[110], cur, pre;

int n, m;

void getline(point p1, point p2, double &a, double &b, double &c) //获得中垂线
{
    point p3 = point( (p1.x + p2.x)/2, (p1.y + p2.y)/2 );
    a = p1.x - p2.x;
    b = p1.y - p2.y;
    c = - a * p3.x - b * p3.y;
}

point intersect(point p1, point p2, double a, double b, double c)
{
    double u = fabs(a * p1.x + b * p1.y + c);
    double v = fabs(a * p2.x + b * p2.y + c);
    point ans;
    ans.x = (v * p1.x + u * p2.x) / (u + v);
    ans.y = (v * p1.y + u * p2.y) / (u + v);
    return ans;
}

void cut(double a, double b, double c)//切割
{
    int i, tm = 0;
    for(i = 1; i <= m; i++)
    {
        if(a * p[i].x + b * p[i].y + c > eps)
            tp[++tm] = p[i];
        else
        {
            if( a * p[i-1].x + b * p[i-1].y + c > eps)
                tp[++tm] = intersect(p[i-1], p[i], a, b, c);
            if( a * p[i+1].x + b * p[i+1].y + c > eps)
                tp[++tm] = intersect(p[i], p[i+1], a, b, c);
        }
    }

    for(i = 1; i <= tm; i++)
        p[i] = tp[i];
    p[0] = p[tm];
    p[tm+1] = p[1];
    m = tm;
}

double cal(int n, point *p) //多边形面积
{
    int i;
    double s = 0;
    p[n+1] = p[1];
    for(i = 1; i <= n; i++)
        s += p[i].x * p[i+1].y - p[i].y *p[i+1].x;
    return fabs(s) / 2;
}

char str[11];

int main()
{
    //freopen("int.txt", "r", stdin);
    int i, j;
    bool flag = 0;
    double a, b, c;
    pre = point(0, 0);
    m = n = 4;
    p[1] = point(0, 0);
    p[2] = point(0, 10);
    p[3] = point(10, 10);
    p[4] = point(10, 0);
    p[5] = p[1];
    p[0] = p[4];
    while( ~scanf("%lf%lf%s", &cur.x, &cur.y, str) )
    {
        getline(pre, cur, a, b, c);
        if(str[0] == 'C') 
        {    
            if(a * pre.x + b * pre.y + c < -eps)
            { a = -a; b = -b; c = -c; }
        }
        else if(str[0] == 'H')
        {
            if(a * cur.x + b * cur.y + c < -eps)
            { a = -a; b = -b; c = -c; }
        }
        else flag = 1; //注意same以后,每次答案都为0;
        if(flag) { puts("0.00"); continue; }
        cut(a, b, c);
        printf("%.2f\n", cal(m, p));    
        pre = cur;
    }
    return 0;
}

模板2:

View Code
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<algorithm>
using namespace std;
#define eps 1e-8

struct point
{
    double x, y;
    bool mark;
    point(){}
    point(double xx, double yy): x(xx), y(yy), mark(1) {}
}cur, pre;

vector<point> p;

point mid(point p1, point p2)
{
    point ans;
    ans.x = (p1.x + p2.x) / 2;
    ans.y = (p1.y + p2.y) / 2;
    return ans;
}

void getline(point p1, point p2, double &a, double &b, double &c)
{
    point p3 = mid(p1, p2);
    a = p1.x - p2.x;
    b = p1.y - p2.y;
    c = -a * p3.x - b * p3.y;
}

point intersect( point p1, point p2, double a, double b, double c)
{
    double u = fabs( a * p1.x + b * p1.y + c );
    double v = fabs( a * p2.x + b * p2.y + c );
    point ans;
    ans.x = (v * p1.x + u * p2.x) / (u + v);
    ans.y = (v * p1.y + u * p2.y) / (u + v);
    return ans;
}

void cut(double a, double b, double c)
{
    int i;
    point tp;
    for(i = 0; i < p.size(); i++)
    {
        if(a * p[i].x + b * p[i].y + c > eps)
            p[i].mark= 1;
        else p[i].mark = 0;
    }
    p.push_back( p[0] );
    for(i = 0; i < p.size() - 1; i++)
        if( p[i].mark^p[i+1].mark == 1)
        {
            tp = intersect(p[i], p[i+1], a, b, c);
            p.insert(p.begin()+i+1, tp);
            i++;
        }
    p.pop_back();
    for(i = 0; i < p.size(); i++)
        if(p[i].mark == 0)
            p.erase(p.begin()+i), i--;
}

double cal()
{
    p.push_back(p[0]);
    double s = 0;
    int i;
    for(i = 0; i < p.size() - 1; i++)
        s += p[i].x *p[i+1].y - p[i].y * p[i+1].x;
    p.pop_back();
    return fabs(s)/2;
}

char str[11];
int main()
{
    //freopen("int.txt", "r", stdin);
    int i, j;
    bool flag = 0;
    double a, b, c;
    p.clear();
    p.push_back( point (0, 0));
    p.push_back( point (0, 10));
    p.push_back( point (10, 10));
    p.push_back( point (10, 0));
    pre = point(0, 0);
    while( scanf("%lf%lf%s", &cur.x, &cur.y, str) != EOF )
    {
        getline(pre, cur, a, b, c);
        if(str[0] == 'C') 
        {
            if(a * pre.x + b * pre.y + c < -eps)
            { a = -a; b = -b; c = -c;}
        }
        else if(str[0] == 'H')
        {
            if(a * cur.x + b * cur.y + c < -eps)
            { a = -a; b = -b; c = -c;}
        }
        else flag = 1;
        if(flag) { printf("0.00\n"); continue; }
        cut(a, b, c);
        printf("%.2f\n", cal());
        pre = cur;
    }
    return 0;
}

 

 

posted @ 2012-09-07 23:37  To be an ACMan  Views(442)  Comments(0)    收藏  举报