Rezolvare completă PbInfo #1036 Parc1

Un parc de formă dreptunghiulară este format din zone pietonale şi piste de biciclete. Reprezentând harta parcului într-un sistem cartezian, cu coordonata colţului stânga-jos (0,0), pistele de biciclete sunt reprezentate prin dungi orizontale sau verticale colorate cu gri, iar zonele pietonale au culoarea albă, ca în figura din dreapta.

Vizitatorii parcului se pot plimba liber pe zonele pietonale în orice direcţie, însă pistele de biciclete se vor traversa, în linie dreaptă, paralel cu axele. În figura alăturată avem un parc de dimensiuni 10 x 8, cu piste de biciclete verticale între 2 şi 4 respectiv 5 şi 8, şi orizontale între 0 şi 1 respectiv între 2 şi 4. Gigel se află în punctul A(1,1) şi poate sa ajungă pe drumul cel mai scurt la prietenul lui, în punctul B(8,7) deplasându-se astfel: porneşte din punctul (1,1) şi parcurge un traseu format din segmente cu extremităţile în punctele de coordonate (1.5 , 2) (1.5, 4) (2 , 5) (4 , 5) (5 , 7) şi în final ajunge în punctul de coordonate (8 , 7).

Lungimea totală a drumului va fi aproximativ 11.4721359.

Cerința

Cunoscând dimensiunile parcului, coordonatele lui Gigel, coordonatele prietenului lui şi poziţiile pistelor de biciclete, să se calculeze lungimea drumului minim şi numărul drumurilor distincte de lungime minimă.

Date de intrare

Fișierul de intrare parc1.in conține pe prima linie două numere naturale Xparc şi Yparc separate prin spaţiu, reprezentând dimensiunile parcului în direcţiile Ox respectiv Oy. Linia a doua va conţine patru numere separate prin spaţiu xG, yG, xpr şi ypr ce reprezintă coordonatele lui Gigel şi coordonatele prietenului lui. Linia a treia va conţine un număr natural m, reprezentând numărul pistelor verticale. Următoarele m linii vor conţine perechi de valori de pe axa Ox ce delimitează câte o pistă de biciclete verticală. Următoarea linie va conţine un număr natural n, reprezentând numărul pistelor orizontale. Următoarele n linii vor conţine perechi de valori de pe axa Oy ce delimitează câte o pistă de biciclete orizontală.

Date de ieșire

Fișierul de ieșire parc1.out va conține pe prima linie lungimea minimă a drumului cerut de problemă, un număr real. Linia a doua va conţine numărul drumurilor minime distincte, un număr natural.

Restricții și precizări

  • 0 ≤ xG, xpr ≤ Xparc ≤ 30 000, 0 ≤ yG, ypr ≤ Yparc ≤ 30 000;
  • 0 < m, n < 2000;
  • perechile de numere naturale ce definesc o pistă nu sunt ordonate;
  • pistele orizontale, şi cele verticale nu sunt ordonate în fişierul de intrare;
  • două piste de aceeaşi direcţie nu se suprapun;
  • Gigel şi prietenului lui sunt pe zone pietonale (incluzând şi marginile acestora);
  • două drumuri sunt distincte dacă diferă prin cel puţin un punct;
  • numărul de drumuri distincte nu va depăşi 1 000 000 000;
  • lungimea drumului din fişierul de ieşire este un număr real ce se va accepta cu eroare maxima de 0.01;
  • prima cerinţă valorează 40% din punctaj, iar a doua valorează 60% din punctaj.

parc1.in

10 8
1 1 8 7
2
5 8 
2 4
2
4 2
0 1

parc1.out

11.472136
1

Explicație

  • lungimea drumului minim a fost calculată în exemplul de mai sus, rezultatul se poate tipări cu oricâte zecimale, diferenţa absolută faţă de rezultatul oficial să nu difere cu mai mult de 0.01
  • există un singur drum de lungime minimă

Cum e corect?

cout < "As la info"; cout << "As la info"; cout >> "As la info";

Felicitări! Poți mai mult?

Avem sute de probleme pentru tine, fiecare cu explicații ușor de înțeles.

Greșit, dar nu-i bai!

Antrenează-te cu sutele de probleme pe care ți le-am pregătit. Îți explicăm fiecare problemă în parte.

Rezolvare

Iată rezolvarea de 100 de puncte pentru problema Parc1:

//Solutia oficiala
//100 puncte
#include <iostream>
#include<cstdio>
#include<cmath>
using namespace std;

void scufundare(int p, int a[2][10000],int n)
{   int pozmax=p;
    if (2*p<=n && a[0][pozmax]<a[0][2*p]) pozmax=2*p;
    if (2*p+1<=n && a[0][pozmax]<a[0][2*p+1]) pozmax=2*p+1;
    if (p!=pozmax)
    {   swap(a[0][p],a[0][pozmax]);
        swap(a[1][p],a[1][pozmax]);
        scufundare(pozmax,a,n);
    }
}

void heapsort(int a[2][10000],int n)      // pistele de biciclete le sortez in ordine crescatoare
{   int i;
    for (i=n/2;i>=1;--i)
        scufundare(i,a,n);
    for (i=n;i>1;--i)
    {   swap(a[0][1],a[0][i]);
        swap(a[1][1],a[1][i]);
        scufundare(1,a,i-1);
    }
}

int main()
{   int pv[2][10000],po[2][10000],xp,yp,xg,yg,xpr,ypr,m,n,i,j,p2,sv[10000],so[10000];
    int startv, finishv,starto,finisho,xinv=0,yinv=0,d_oriz,d_vert,cx,cy,semnx=1,semny=1;
    int kx,ky,segmx[10000],segmy[10000];
    double lung;
    freopen("parc1.in","r",stdin);
    freopen("parc1.out","w",stdout);
    scanf("%d %d
",&xp,&yp);
    scanf("%d %d %d %d
",&xg,&yg,&xpr,&ypr);
    if (xpr<xg)    // voi prelucra doar un singur caz: cand gigel este in stanga-jos
    {   xinv=1;       // iar prietenul este in dreapta-sus
        xg=xp-xg;    //pentru a rezolva acest lucru, voi folosi simetrii pe OX si OY daca este necesar
        xpr=xp-xpr;
        semnx=-1;
    }
    if (ypr<yg)    
    {   yinv=1;   
        semny=-1;
        yg=yp-yg;
        ypr=yp-ypr;
    }
    if (xpr==xg)
    {   printf("%d
1
",ypr-yg);
        return 0;
    }
    if (ypr==yg)
    {   printf("%d
1
",xpr-xg);
        return 0;
    }
    scanf("%d
",&m);
    if (xinv)          
        for (i=1;i<=m;++i)
        {   scanf("%d %d
",&pv[0][i],&pv[1][i]);
            if (pv[0][i]<pv[1][i]) swap(pv[0][i],pv[1][i]);
            pv[0][i]=xp-pv[0][i];                           // citesc pistele verticale (x-urile) si daca e nevoie
            pv[1][i]=xp-pv[1][i];                           // transform in simetricul lor sa le prelucrez de la st. da dr.
        }
    else
        for (i=1;i<=m;++i)
        {   scanf("%d %d
",&pv[0][i],&pv[1][i]);
            if (pv[0][i]>pv[1][i]) swap(pv[0][i],pv[1][i]);
        }
    heapsort(pv,m);                           // sortez punctele in ordine crescatoare
    scanf("%d
",&n);
    if (yinv)
        for (i=1;i<=n;++i)
        {   scanf("%d %d
",&po[0][i],&po[1][i]);            // citesc pistele orizontale (y-urile) si daca e nevoie
            if (po[0][i]<po[1][i]) swap(po[0][i],po[1][i]);  // le transform in simetricul lor sa le parcurg de jos in sus 
            po[0][i]=yp-po[0][i];
            po[1][i]=yp-po[1][i];
        }
    else
        for (i=1;i<=n;++i)
        {   scanf("%d %d
",&po[0][i],&po[1][i]);
            if (po[0][i]>po[1][i]) swap(po[0][i],po[1][i]);
        }
    heapsort(po,n);                           // sortez punctele in ordine crescatoare
    sv[0]=0;
    for(i=1;i<=m;++i)
        sv[i]=sv[i-1]+pv[1][i]-pv[0][i];       // memorez grosimile pistelor, ca si sume partiale
    so[0]=0;
    for(i=1;i<=n;++i)
        so[i]=so[i-1]+po[1][i]-po[0][i];       //  idem

    startv=1;
    while (xg>pv[0][startv]) ++startv;        // ma uit cate piste verticale sunt intre Gigel si prietenul lui
    finishv=m;
    while (xpr<pv[1][finishv]) --finishv;

    starto=1;
    while (yg>po[0][starto]) ++starto;       // ma uit cate piste orizontale sunt intre Gigel si prietenul lui
    finisho=n;
    while (ypr<po[1][finisho]) --finisho;
    d_oriz=sv[finishv]-sv[startv-1];         // grosimea pistelor verticale
    d_vert=so[finisho]-so[starto-1];         // grosimea pistelor verticale
    cx=xpr-xg-d_oriz;               // cea mai scurta distanta dintre doua puncte se calculeaza dintr-un triunghi
    cy=ypr-yg-d_vert;                  // dreptunghic cu catele cx si cy
        //cx si cy reprezinta lungimile catetelor triunghiului dreptunghic fara pistele orizontale si verticale
    lung=sqrt((float)(cx*cx+cy*cy))+d_oriz+d_vert;    // la lungimea ipotenuzei se adauga distantele orizontale si verticale    
    segmx[0]=pv[0][startv]-xg;kx=0;
    for (i=startv+1;i<=finishv;++i)
    {   ++kx;   
        segmx[kx]=segmx[kx-1]+pv[0][i]-pv[1][i-1];
    }
    segmy[0]=po[0][starto]-yg;ky=0;
    for (i=starto+1;i<=finisho;++i)
    {   ++ky;
        segmy[ky]=segmy[ky-1]+po[0][i]-po[1][i-1];
    }
    
    p2=1;
    i=j=0;
    while(i<=kx && j<=ky)
        if (segmx[i]*cy==segmy[j]*cx)
        {   p2*=2;
            ++i;++j;
        }
        else
            if (segmx[i]*cy>segmy[j]*cx)
                ++j;
            else
                ++i;
    printf("%lf
",lung);
    printf("%d
",p2);
    return 0;
}

Atenție

Enunțurile afișate pe această pagină aparțin exclusiv site-ului PbInfo. Astfel, pentru ștergerea conținutului, puteți să ne contactați la adresa Adresa de email.

Rezolvarea problemei #1036 Parc1

Pe această pagină găsești rezolvarea de 100 de puncte pentru problema #1036 Parc1 de pe PbInfo.ro. Atenție: nu încurajăm copiatul codului! Totuși, credem cu tărie că analizarea unei soluții corecte este o metodă foarte ușoară de a învăța informatică, astfel că oferim sursele pentru peste 1500 de probleme de pe platforma PbInfo.ro.

Pentru rezolvări PbInfo de la peste 1500 de probleme, vă invităm să intrați pe site-ul nostru!