Cod sursa(job #730597)

Utilizator venom4u31Manea Constantin venom4u31 Data 6 aprilie 2012 17:19:51
Problema Rubarba Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 8.6 kb
#include <iostream>
#include <fstream>
#include <math.h>
#include <cstdlib>

using namespace std;
ifstream f("rubarba.in");
ofstream g("rubarba.out");
typedef struct cel2
{ struct cel2 *pre, *urm;  /* legaturi spre celulele vecine */
  float x, y;
} TCel2, *TL2;
float angle(TL2 p1, TL2 p2, TL2 p3);
TL2 f1(TL2 l, TL2 a);
TL2 search(TL2 l, TL2 r);
float d3p(TL2 p1, TL2 p2, TL2 p3);
TL2 proj(TL2 p1, TL2 p0, TL2 q);


TL2 proj(TL2 p1, TL2 p0, TL2 q)//coordonatele proiectiei lui q pe dreapta p1p0
{
    float x, y, a, b, c, d, s1, s2;
    a=(p1->x)-(p0->x);
    b=(p1->y)-(p0->y);
    c=(p0->y)-(p1->y);
    d=(p1->x)-(p0->x);
    s1=(q->x)*((p1->x)-(p0->x))+(q->y)*((p1->y)-(p0->y));
    s2=(p0->y)*(p1->x-p0->x)-(p0->x)*((p1->y)-(p0->y));
    x=(d*s1-b*s2)/(a*d-b*c);
    y=(c*s1-a*s2)/(b*c-a*d);
    TL2 sol = (TL2)malloc (sizeof(TCel2));
    sol->x=x;
    sol->y=y;
    return sol;

}

float d3p(TL2 p1, TL2 p2, TL2 p3)//distanta de la p3 la p1p2
{
    float x1=p1->x, y1=p1->y, x2=p2->x, y2=p2->y, x3=p3->x, y3=p3->y;
    float a, b, d, s;
    a=(y2-y1)/(x2-x1);
    b=y1-a*x1;
    s=sqrt(a*a+1);
    d=(a*x3-y3+b)/s;
    return d;
}

TL2 search(TL2 l, TL2 r)
{
    TL2 p;
    for(p=l->urm;p!=l;p=p->urm)
    if(p->x==r->x&&p->y==r->y)
    return p;
    return NULL;
}



float angle(TL2 p1, TL2 p2, TL2 p3)//unghiul in sens trigonometric de la dreapta p1p2 la p1p3
{
    /*
    Vectorial product
    | e1   e2  e3 |
    |dx21 dy21 z1 | = P
    |dx31 dy31 z2 |


    */

    float x1=p1->x, y1=p1->y, x2=p2->x, y2=p2->y, x3=p3->x, y3=p3->y;
    float dx21 = x2-x1;
    float dx31 = x3-x1;
    float dy21 = y2-y1;
    float dy31 = y3-y1;
    float m12 = sqrt( dx21*dx21 + dy21*dy21 );
    float m13 = sqrt( dx31*dx31 + dy31*dy31 );
    //float v=(dy21-dy31)-(dx21-dx31)+(dx21*dy31-dx31*dy21);
    float v=(dx21*dy31-dx31*dy21);
    v=v/abs((int)v);


    if(m12==m13||m12*m13==0)
    return 100;


    return v*acos( (dx21*dx31 + dy21*dy31) / (m12 * m13) );
}

TL2 f1(TL2 l, TL2 a)
{
    TL2 p, q, r, aux;
    float ang1, ang2, s1, s2;
    for(p=l->urm, q=p->urm;p!=l->pre;p=p->urm, q=q->urm)
    {
        for(r=a->urm;r!=a;r=r->urm)
        {
            ang1=angle(p, q, r);
            s1=sin(ang1);
            if(p->pre!=l)
                ang2=angle(p, p->pre, r);
            else
                ang2=angle(p, p->pre->pre, r);
            s2=sin(ang2);

            aux=search(l, r);
            if(!aux&&ang1+ang2<90)
            {
            if(s1>=0&&s2>=0)
            {
                aux = (TL2)malloc (sizeof(TCel2));
                p->urm=aux;
                aux->urm=q;
                q->pre=aux;
                aux->pre=p;
                q=aux;
                aux->x=r->x;
                aux->y=r->y;
                r=a;
            }
            if(s1>0&&s2<0)
            {
                aux = (TL2)malloc (sizeof(TCel2));
                aux->urm=q;
                aux->pre=p->pre;
                p->pre->urm=aux;
                q->pre=aux;
                p->urm=NULL;
                p->pre=NULL;
                q=aux;
                p=aux->pre;
                aux->x=r->x;
                aux->y=r->y;
                r=a;
            }
            }
            else if(ang1+ang2<90)
            {
                if(s1>0){
                q->urm->pre=q->pre;
                q->pre->urm=q->urm;
                q->urm=NULL;
                q->pre=NULL;
                q=p->urm;
                r=a;}
            }


        }
    }
    /*
    for(p=l->urm, q=p->urm->urm;p!=l;p=p->urm, q=q->urm)
    {
        if(q==l)
        {
            q=q->urm;
            r=l->pre;
        }
        else r=q->pre;
        ang1=angle(p, q, r);
        s1=sin(ang1);
        if(p->pre!=l)
            ang2=angle(p, p->pre, r);
        else
            ang2=angle(p, p->pre->pre, r);
        s2=sin(ang2);
        if(s1*s2<0)
        {
            r->urm->pre=r->pre;
            r->pre->urm=r->urm;
            r->urm=NULL;
            r->pre=NULL;
        }
    }*/
return l;
}


int main()
{
    //double xmax=0, ymax=0, xmin=1000000, ymin=1000000, n, i, x, y, xp1, xp2, yp1, yp2;
    int n, i;
    float xmax=0, ymax=0, xmin=1000000, ymin=1000000, smin=1000000, dmax=0, d;
    TL2 a, b, p, l, m1, m2, m3, m4, q, r;


    //a = (TL2)(new TL2);   /* incearca alocare santinela */
    a = (TL2)malloc (sizeof(TCel2));   /* incearca alocare santinela */
    if (a)                              /* aux contine adresa santinelei */
    { a->pre = a->urm = a;          /* completeaza celula */
    }
    b = (TL2)malloc (sizeof(TCel2));   /* incearca alocare santinela */
    if (b)                              /* aux contine adresa santinelei */
    { b->pre = b->urm = b;          /* completeaza celula */
    }
    l = (TL2)malloc (sizeof(TCel2));   /* incearca alocare santinela */
    if (l)                              /* aux contine adresa santinelei */
    { l->pre = l->urm = l;          /* completeaza celula */
    }



    m1= (TL2)malloc (sizeof(TCel2));
    if (m1)                              /* aux contine adresa santinelei */
    { m1->pre = m1->urm = m1;          /* completeaza celula */
    }
    m2= (TL2)malloc (sizeof(TCel2));
    if (m2)                              /* aux contine adresa santinelei */
    { m2->pre = m2->urm = m2;          /* completeaza celula */
    }
    m3= (TL2)malloc (sizeof(TCel2));
    if (m3)                              /* aux contine adresa santinelei */
    { m3->pre = m3->urm = m3;          /* completeaza celula */
    }
    m4= (TL2)malloc (sizeof(TCel2));
    if (m4)                              /* aux contine adresa santinelei */
    { m4->pre = m4->urm = m4;          /* completeaza celula */
    }

    f>>n;
    for(i=1;i<=n;i++)
    {

        p= (TL2)malloc (sizeof(TCel2));
        f>>(p->x);
        f>>(p->y);
        p->urm = a;
        p->pre = a->pre;
        a->pre->urm = p;
        a->pre = p;

        if(p->x > xmax)
        {
            xmax=p->x;
            m2->x=p->x;
            m2->y=p->y;
        }

        if(p->x<xmin)
        {
            xmin=p->x;
            m4->x=p->x;
            m4->y=p->y;
        }
        if(p->y>ymax)
        {
            ymax=p->y;
            m1->x=p->x;
            m1->y=p->y;
        }
        if(p->y<ymin)
        {
            ymin=p->y;
            m3->x=p->x;
            m3->y=p->y;
        }
    }

    /*cout<<a->urm->x<<endl;
    cout<<a->urm->urm->x<<endl;
    cout<<a->urm->urm->urm->x<<endl;
    cout<<a->urm->urm->urm->urm->x<<endl;*/




    l->urm=m1;
    m1->pre=l;
    m1->urm=m2;
    m2->pre=m1;
    m2->urm=m3;
    m3->pre=m2;
    m3->urm=m4;
    m4->pre=m3;
    m4->urm=l;
    l->pre=m4;
    l=f1(l, a);
    cout<<"Puncte contur:\n";
    /*for(p=l->urm;p!=l;p=p->urm)
    cout<<p->x<<' '<<p->y<<endl;*/

    TL2 x1, x2, x3;
    x1=(TL2)malloc (sizeof(TCel2));
    x2=(TL2)malloc (sizeof(TCel2));
    x3=(TL2)malloc (sizeof(TCel2));

    float ang, dleft=0, dright=0, apq, bpq, u;

    for(p=l->urm, q=p->urm;p!=l->pre;p=p->urm, q=q->urm)
    {
        dright = 0;
        dleft=0;
        dmax=0;
        for(r=q->urm;r!=p;r=r->urm)
        {

            if(r==l)
                r=r->urm;
            if(r->x==p->x&&r->y==p->y)
                break;
            d=d3p(p,q,r);
            if(d<0)
                d=d*(-1);
            if(d>dmax)
                {dmax=d;
                b=r;}
        }
        apq=((p->y)-(q->y))/((p->x)-(q->x));
        bpq=(p->y)-(apq*(p->x));
        //x3->y=b->y;
        //x3->x=((x3->y)-bpq)/apq;

        //ang=angle(x3,p,q);
        //u=(((b->x)-(p->x))*((q->x)-(p->x))+((b->y)-(p->y))*((q->y)-(p->y)))/(((p->y)-(q->y))+((p->x)-(q->x)));
        //x2->x=(p->x)+u*((q->x)-(p->x));
        //x2->y=(p->y)+u*((q->y)-(p->y));

        x2=proj(p, q, b);



        for(x1=b->urm;x1!=b;x1=x1->urm)
        {
            if(x1==l)
            x1=x1->urm;
            if(x1->x==b->x&&x1->y==b->y)
                break;
            d=d3p(b, x2, x1);
            if(d>dright)
            dright=d;
            if(d<dleft)
            dleft=d;

        }
        dleft=dleft*(-1);
        if((dright+dleft)*dmax<smin)
        smin=(dright+dleft)*dmax;
    }
    int prec=0;
    float cont=smin;
    while(cont>=1)
    {
        prec++;
        cont/=10;
    }
    g.precision(prec+2);
    g<<smin<<endl;
    //cout<<"\nAria minima a dreptunghiului circumscris: \n"<<smin;
    f.close();
    g.close();
    //getch();
    return 0;
}