From: | "Mihai Patrascu" <mihai_p@pcnet.ro> | Block Address | Add to Address Book |
To: | "probleme" <probleme@ldc.ro> |
Subject: | Re: probleme de geometrie |
Date: | Tue, 10 Apr 2001 13:19:52 +0300 |
|
|
> Test geometrie
> ~~~~~~~~~~~~~~~~~~
Problemele sunt interesante. De unde le ai? Mai trimite daca mai ai.
> 1. Se dau coordonatele a n puncte din plan (n<=1000). Gasiti o
dreapta
> care contine cele mai multe din punctele date.
> Intrare : fisierul g1.in - contine pe prima linie numarul natural n,
iar
> pe urmatoarele n linii perechi de numere intregi din intervalul
[-1000,1000]
> Iesire : in fisierul g1.out se va scrie pe o linie numarul maxim de
> puncte coliniare iar pe urmatoarele linii coordonatele acestor
puncte.
Solutie in O(N*N*lgN). Pentru fiecare punc, translatezi tot sistemul ca
si
cum punctul ala ar fi originea si sortezi punctele dupa panta cu
originea.
In vectorul sortat, punctele coliniare apar pe pozitii consecutive cu
pante
egale. O idee care iti reduce timpul de rulare si te ajuta putin si la
implementare e sa sortezi la inceput punctele dupa cheia primara x si
cheia
secundara y si pentru fiecare punct sa consideri apoi decat punctele
din
cadranele I si II fata de el.
Pentru ca ai numere naturale de modul max 1000, sortarea dupa pante se
face
superb. Fie (x,y) coordonatele punctului dupa translatie. In loc de
panta
(double) x/y, poti tine perechea de numere (x/gcd(x,y), y/gcd(x,y))
(scuzati
romgleza, gcd e greatest common divisor). Aceasta este o pereche de
doua
short-uri, care le poti pune in structura de date:
union {
long u;
struct {
short a, b;
} pair;
};
Poti adica sorta numere intregi (campul u). Sortarea merge (mult) mai
repede. Justificarea de ce merge asa e putin mai complicata, dar va
prindeti
voi.
> 2. Gasiti cercul care contine in interior sau pe circumferinta o
multime
> de puncte date si care are centrul in unul din aceste puncte.
> Intreare : Fisierul g2.in contine pe o linie numarul de puncte
<=300, iar
> pe urmatoarele linii coordonatele acestor puncte, perechi de numere
> intregi din intervalul [-200,200] separate prin spatii.
> Iesire : Fisierul g2.out va contine 3 numere : o pereche de numere
fiind
> coordonatele centrului, al treilea numar raza cercului cu 2 zecimale
exacte.
De ce nu poti considera fiecare punct si apoi sa gasesti cel mai
departat
punct de el? O(N**2). Daca centrul nu e intr-unul din puncte, s-a dat o
rezolvare mai demult pe lista.
> 3. Gasiti o linie franta de lungime minima care uneste n puncte
(n<=100),
> pornind de la un punct dat Po. Punctele au coordonate intregi (x,y)
cu
> 1<=x<=100, 1<=y<=100.
> Intrare : fisierul g3.in contine punctele ca mai sus, primul punct
fiind
Po.
> Iesire : fisierul g3.out contine pe primul rand lungimea minima, cu
3
> zecimale, iar pe urmatoarele randuri coordonatele punctelor, in
ordinea in
> care sunt unite, incepand cu Po.
Problema este NP. E vorba de gasirea unui lant hamiltonian intr-un graf
planar. Faptul ca iti da punctul de pornire nu ajuta prea mult.
Problema s-a
mai dat la o nationala la clasa X acum vreo doi ani.
O abordare simpla e sa faci un greedy oarecare si eventual un back
omorat
dup-aia (cu conditii de oprire destepte in back). Cu asta s-a luat max
la
nationala aia.
O idee mai savanta de euristica e sa incerci sa gasesti un lant
hamiltonian
bitonic. Un astfel de lant porneste din Po, trece prin unele puncte
pana la
P de x maxim, crescand mereu x-ul punctelor si apoi se intoarce scazand
mereu x-ul trecand toate punctele pe care nu le-a luat de prima data.
Deseori un lant bitonic e suficient de aproape de optim. Poti incerca
si
dupa y, nu numai dupa x si apoi inlocuind "spre x maxim" cu "spre x
minim"
(4 euristici in total). Un astfel de lant minim se determina cu o
dinamica
cu un tablou de N*N in O(N*N), cred ca va prindeti cum.
Pentru problema unui ciclu hamiltonian intr-un graf planar, exista un
algoritm de aproximare destul de bun care scoate un ciclu de cel mult 2
ori
mai mare ca optimul. Ideea e sa faci un MST (minimum spanning tree -
arbore
partial minim) si sa-l parcurgi DF. Unind punctele in ordinea primei
atingeri iti da un astfel de ciclu. Va las pe voi sa va dati seama de
ce e
de cel mult 2 ori mai lung ca optimul (cheia demonstratiei e ca graful
e
planar). Acest algoritm se poate adapta pentru lant hamiltonian, taind
muchia care revine in Po la sfarsitul ciclului. O optimizare e sa nu
parcurgi DF oricum, ci astfel incat ultimul nod atins sa fie cel mai
departat de Po. Complexitatea per total e O(N*N) timp cu O(N) memorie.
> 4. Se dau n puncte (n<=200) oricare 3 necoliniare. Gasiti un romb
cu
> varfurile in punctele date, (daca exista).
O rezolvare evidenta e pentru fiecare punct sortezi celelalte puncte
dupa
distanta la punctul referinta (cheia primara) si dupa panta cu punctul
referinta (cheia secundara). Apoi iei oricare doua puncte aflate la
aceeasi
distanta (astfel de puncte sunt consecutive in lista) si formezi rombul
din
astea doua puncte si punctul de referinta. Al patrulea varf il poti
cauta in
O(lgN) fiindca poti calcula distanta la punctul referinta si panta lui
e
media aritmetica pentru pantele celor doua puncte alese. Memorie e O(N)
si
timp e Omega((N**2)*lgN) si O((N**3)*lgN). Mai strans nu stiu, dar
pentru
200 sigur intra in timp.
Exista si o rezolvare simplu de implementat O((N**2)*lgN) (problema ar
fi ca
memoria e O(N**2) - pe Linux am putea avea n <= 1000 fara probleme).
Ideea e
sa unesti oricare doua puncte. Pentru fiecare segment tii mijlocul si
panta.
Acum trebuie sa determini daca exista doua segmente perpendiculare cu
acelasi mijloc.
Sa presupunem ca coordonatele sunt numere intregi de modul < 1000.
Centrele
le tii ca numere intregi (tii (2x,2y) in loc de (x,y)). Panta o tii la
fel
ca la problema 1, cu o singura modificare. Segmente perpendiculare
inseamna
produsul pantelor egal cu -1. Deoarece oricare trei puncte sunt
necoliniare,
nu avem doua structuri egale (aceleasi centre si aceleasi pante). Deci
fiecare panta negativa o modificam si tinem (-1/m) in loc de m (sa
numim
asta panta normalizata). Problema se reformuleaza: "gasiti daca exista
doua
segmente cu mijloacele si pantele normalizate egale". Asta se face usor
cu o
sortare si apoi verificam daca doua elemente consecutive sunt egale.
Pentru
considerente similare cu prob 1, putem sorta numere intregi de 64 de
biti in
loc de structuri.
Implementarea e scurta si simpla, iar pe Linux merge pentru N=1000 in
0.7
sec daca stii s-o faci ca lumea.
> 5. Se dau n puncte cu coordonate pozitive. Gasiti un dreptunghi de
arie
> minima care contine in interior sau pe frontiera cel putin jumatate
din
> punctele date.
> Intrare : Fisierul g5.in contine numarul de puncte, numar natural
<=1000
> si coordonatele punctelor, numere reale cu 3 zecimale.
> Iesire : Fisierul g5.out contine coordonatele varfurilor stanga jos
si
> dreapta sus ale dreptunghiului gasit, cu 3 zecimale.
Hmmm, dupa marimea datelor cred ca trebuie un algoritm O~(N**2)... ma
mai
gandesc. [Pentru cine nu e tare la teorie, O~ se citeste O moale, tilda
se
scrie deasupra O-ului si e ca si O numai ca eliminam orice factor lgN
din
paranteza].
> 6. Se dau n puncte in plan (n<=1000) de coordonate intregi mai mici
in
> modul ca 250, oricare 3 necoliniare. Gasiti un triunghi cu varfurile
in
> punctele date de perimetru minim.
> Intrare : fisierul g6.in - ca mai sus
> Iesire : fisierul g6.out - varfurile.
Si aicea trebuie tot ceva O~(N**2). Cred ca am chiar o chestie O(NlgN).
Presupun ca stiti algoritmul in O(NlgN) pentru cele mai apropiate doua
puncte. Cred ca merge tot o chestie similara. Singura neclaritate e
reunirea
celor doua partitii. Se demonstreaza usor ca e suficient sa se
considere o
banda de P/2 in jurul dreptei verticale dupa care s-a partitionat (unde
P e
minimul dintre perimetrele minime gasite de o parte si de alta). Tot ce
mai
ramane sa demonstrez e ca incap O(1) puncte intr-un patrat de P/2*P/2
astfel
incat sa nu poti forma din ele un triunghi cu perimetrul mai mic de P.
Nu
prea imi dau seama cat e constanta din O(1), dar nu prea conteaza decat
daca
exista. Intuitiv exista si am si niste idei cum s-ar putea demonstra.
La
concurs as fi implementat asta fara nici un dubiu, deoarece chiar daca
ma
insel si nu exista o astfel de constanta, oricum in practica algoritmul
va
lua destul teste.
mihai_p
Privacy Policy-
Terms of Service
-
Guidelines
Copyright © 1994-2001
Yahoo! Inc. All rights reserved.