【TOJ 2034】C++实验:面积排序(已知三点,利用二阶行列式求三角形面积)

描述

给定三角形、矩形、圆等二维几何图形,请根据面积从大到小进行排序。

主函数里的代码已经给出,请补充完整,提交时请勿包含已经给出的代码。

int main()
{
	vector<CShape*> vec; //为了使用多态,使用指针数组
	string name;
	int num[3]= {};  //用于存储3种形状的ID
	while(cin>>name)
	{
		if(name=="rectangle")
		{
			CPoint p1, p2;
			cin>>p1>>p2;
			vec.push_back(new CRectangle(name, ++num[0], p1, p2));
		}
		else if(name=="triangle")
		{
			CPoint p1, p2, p3;
			cin>>p1>>p2>>p3;
			vec.push_back(new CTriangle(name, ++num[1], p1, p2, p3));
		}
		else
		{
			CPoint center;
			double r;
			cin>>center>>r;
			vec.push_back(new CCircle(name, ++num[2], center, r));
		}
	}
	sort(vec.begin(), vec.end(), cmp);
	for(int i=0;i<vec.size();i++)
	{
		cout<<vec[i]->GetName()<<" "<<setiosflags(ios::fixed)<<setprecision(3)<<vec[i]->Area()<<endl;
		delete vec[i];
	}
	
	return 0;
}

输入

输入数据包括有多行,每行为一个几何图形(不超过100个几何图形)。各种几何图形的输入格式如下:

三角形(x1,y1,x2,y2,x3,y3分别为三角形顶点坐标):
triangle x1 y1 x2 y2 x3 y3

矩形(x1,y1,x2,y2为矩形某对角线的端点,矩形的边与坐标轴平行)
rectangle x1 y1 x2 y2

圆(x1,y1为圆心坐标,r为半径)
circle x1 y1 r

输出

对各个图形分别进行编号命名,三角形命名为triangle1、triangle2...,矩形命名为rectangle1、rectangle2...,圆命名为circle1、circle2...

然后按照面积从大到小进行排序,如果面积相同,则根据名字按照字典序排序。每行输出一个形状的名字以及面积,用空格分隔,面积保留3位小数。

样例输入

rectangle 0.0 0.0 1.0 2.0
circle 0.0 0.0 1.0
triangle 0.0 0.0 1.0 1.0 1.0 0.0
rectangle 0.0 0.0 1.0 1.0
circle 0.0 0.0 2.0

样例输出

circle2 12.566
circle1 3.142
rectangle1 2.000
rectangle2 1.000
triangle1 0.500

题解

由于海伦公式的计算会有误差,所以我们利用二阶行列式计算三角形的面积:

设A(x1,y1),B(x2,y2),C(x3,y3)在坐标系中中顺序为三点按逆时针排列
S=1/2[(x1y2-x2y1)+(x2y3-x3y2)+(x3y1-x1y3)]
ps:最好给面积加个绝对值,有时候会出现负值
#include<bits/stdc++.h>
#define pi acos(-1)
using namespace std;
string ch(string s,int x)
{
    stringstream ss;
    ss<<s<<x;
    ss>>s;
    return s;
}
class CPoint{
public:
    double x,y;
    CPoint(double x=0,double y=0):x(x),y(y){}
    friend istream &operator>>(istream &is,CPoint&p)
    {
        is>>p.x>>p.y;
        return is;
    }
};
class CShape{
public:
    double m;
    string name;
    CShape(string name,double m):m(m),name(name){}
    double Area(){return m;}
    string GetName(){return name;}
};
int cmp(CShape *a,CShape *b)
{
    if(a->m>b->m)return 1;
    if(a->m==b->m)
    {
        if(a->name<b->name)
            return 1;
        else return 0;
    }
    return 0;
}

class CTriangle:public CShape{
private:
    CPoint p1, p2, p3;
    int num;
public:
    CTriangle(string name,int num,CPoint p1,CPoint p2,CPoint p3)
    :p1(p1),p2(p2),p3(p3),CShape(ch(name,num),fabs(0.5*((p1.x*p2.y-p2.x*p1.y)+(p2.x*p3.y-p3.x*p2.y)+(p3.x*p1.y-p1.x*p3.y)))),num(++num){}
};

class CRectangle:public CShape{
private:
    CPoint p1, p2;
public:
    int num;
    CRectangle(string name,int num,CPoint p1,CPoint p2)
    :CShape(ch(name,num),fabs((p1.x-p2.x)*(p1.y-p2.y))),num(++num),p1(p1),p2(p2){}
};

class CCircle:public CShape{
private:
    CPoint p;
    int num;
    double r;
public:
    CCircle(string name,int num,CPoint p,double r)
    :CShape(ch(name,num),pi*r*r),num(++num),p(p),r(r){}
};
int main()
{
    vector<CShape*> vec; //为了使用多态,使用指针数组
    string name;
    int num[3]= {};  //用于存储3种形状的ID
    while(cin>>name)
    {
        if(name=="rectangle")
        {
            CPoint p1, p2;
            cin>>p1>>p2;
            vec.push_back(new CRectangle(name, ++num[0], p1, p2));
        }
        else if(name=="triangle")
        {
            CPoint p1, p2, p3;
            cin>>p1>>p2>>p3;
            vec.push_back(new CTriangle(name, ++num[1], p1, p2, p3));
        }
        else
        {
            CPoint center;
            double r;
            cin>>center>>r;
            vec.push_back(new CCircle(name, ++num[2], center, r));
        }
    }
    sort(vec.begin(), vec.end(), cmp);
    for(int i=0;i<vec.size();i++)
    {
        cout<<vec[i]->GetName()<<" "<<setiosflags(ios::fixed)<<setprecision(3)<<vec[i]->Area()<<endl;
        delete vec[i];
    }

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/kannyi/p/9057486.html