τύφλα να 'χει το e-maxx

Shoelace Formula

Η shoelace formula είναι ένας εύκολος τρόπος υπολογισμού του εμβαδού ενός πολυγώνου του οποίου οι ακμές δεν τέμνονται μεταξύ τους. Προσοχή πως το πολύγωνο αυτό δεν είναι απαραίτητα κυρτό. Καθώς η shoelace formula επιστρέφει εμβαδόν με πρόσημο, μπορούμε να τη χρησιμοποιήσουμε για να βρούμε εάν τρία σημεία δημιουργούν δεξιόστροφη ή αριστερόστροφη γωνία.

Shoelace Formula

Δεδομένων σημείων με συντεταγμένες , έχουμε ότι το εμβαδόν του πολυγώνου με άκρα τα σημεία αυτά (με τη σειρά που δίνονται) είναι ίσο με:

Καθώς όμως ο τύπος αυτός μοιάζει ιδιαίτερα περίπλοκος, μπορούμε να χρησιμοποιούμε τον εξής μνημονικό κανόνα:

  1. Πρώτα γράφουμε τα σημεία σε μια στήλη, φροντίζοντας να επαναλάβουμε το πρώτο σημείο στο τέλος:

  2. Έπειτα πολλαπλασιάζουμε διαγώνια τα ζεύγη και τα αθροίζουμε:

    οπότε παίρνουμε

  3. Μετά πολλαπλασιάζουμε διαγώνια τα ζεύγη και αφαιρούμε το άθροισμά τους από το προηγούμενο νούμερο:

    οπότε παίρνουμε

  4. Τέλος παίρνουμε το μισό αυτού του αριθμού, και εάν ενδιαφερόμαστε μόνο στο εμβαδόν, παίρνουμε την απόλυτη τιμή για να είναι πάντα θετικό, οπότε καταλήγουμε στον τύπο

Ο λόγος που λέγεται shoelace formula είναι ότι αν φέρουμε γραμμές που ενώνουν τα ζεύγη που ορίσαμε με το ίδιο χρώμα παραπάνω, το σχήμα θα μοιάζει με κορδόνια παπουτσιού.

Παράδειγμα

Έστω ότι έχουμε το πολύγωνο με άκρα .

Τότε το εμβαδόν του είναι ίσο με

Υλοποίηση

#include <vector> // vector, pair
#include <math.h> // fabs

using namespace std; // vector, pair

#define X first
#define Y second
// Αυτό δεν είναι πάντα καλή ιδέα, αλλά τυχαίνει τα κεφαλαία X και Y να μην εμφανίζονται σε εντολές της c++

double polygon_area(pair<int, int> *pts, int n) {
    int out=0; // Δεν χρειάζεται να χρησιμοποιήσουμε double καθώς όλα τα σημεία είναι ακέραιοι
    for(int i=0; i<n-1; ++i) {
        out += pts[i].X*pts[i+1].Y - pts[i].Y*pts[i+1].X;
    }
    return fabs((double)out)/2;
}

CCW

Μια πολύ χρήσιμη υποπερίπτωση του shoelace formula είναι ο έλεγχος για το αν τρία σημεία στρέφουν αριστερόστροφα ή δεξιόστροφα. Πιο συγκεκριμένα, δεδομένων τριών σημείων , εάν το εμβαδόν που επιστρέφει το shoelace formula (χωρίς να πάρουμε απόλυτη τιμή) είναι θετικό, τότε το βρίσκεται αριστερά της ευθείας που ορίζουν τα , ενώ εάν είναι αρνητικό, τότε το βρίσκεται δεξιά της ευθείας αυτής. Εννοείται πως εάν είναι μηδέν, τα σημεία είναι συνευθειακά. Τα αρχικά CCW σημαίνουν Counter-ClockWise, καθώς η τιμή είναι θετική αν και μόνο αν τα σημεία στρέφουν αντίθετα της φοράς των δεικτών του ρολογιού.

Παραδείγματα

Έστω τα σημεία :

Η τιμή του CCW θα είναι , οπότε όπως βλέπουμε και στο σχήμα τα σημεία στρέφουν δεξιόστροφα.

Εάν τώρα θεωρήσουμε τα σημεία :

Η τιμή του CCW θα είναι , οπότε τα σημεία στρέφουν αριστερόστροφα.

Υλοποίηση

#include <utility> // pair (Εναλλακτικά μπορούμε να χρησιμοποιήσουμε τη βιβλιοθήκη vector)

using namespace std; // pair

#define X first
#define Y second
typedef pair<long long> pll;

long long CCW(pll A, pll B, pll C) {
    return A.X*B.Y - A.Y*B.X + B.X*C.Y - B.Y*C.X + C.X*A.Y - C.Y*A.X;
}

Σημειώνουμε ότι δεν χρειάζεται να χρησιμοποιήσουμε double εάν τα σημεία είναι ακέραιοι, καθώς δεν είναι ανάγκη να πάρουμε το ήμισυ της τιμής του εμβαδού.

Μπορούμε να χρησιμοποιήσουμε το CCW για να βρούμε το εμβαδόν πολυγώνου. Θεωρούμε ότι η υλοποίηση του CCW είναι όπως παραπάνω.

double polygon_area(pair<int, int> *pts, int n) {
    long long out;
    for(int i=0; i<n; ++i) {
        out += CCW(mp(0, 0), pts[i], pts[(i+1)%n]);
    }
    return fabs((double)out)/2;
}

Απόδειξη

H παρακάτω απόδειξη δεν είναι χρήσιμη για τον διαγωνισμό.

Γνωρίζουμε ότι δεδομένων δύο διανυσμάτων , το εξωτερικό τους γινόμενο μας δίνει το εμβαδόν του παραλληλογράμμου που ορίζεται από αυτά τα δύο διανύσματα. Εάν το βρίσκεται αριστερότερα του , τότε το εξωτερικό γινόμενο είναι θετικό, αλλιώς είναι αρνητικό. Το μισό του εξωτερικού γινομένου ισούται με το τρίγωνο που ορίζεται από τα .

Έστω ένα πολύγωνο με άκρα . Ορίζουμε τα διανύσματα με τις συντεταγμένες των σημείων αυτών. Τότε η shoelace formula ισούται με . Ας θεωρήσουμε πρώτα την περίπτωση ενός τριγώνου, όπου δηλαδή . Τότε, ο τύπος μας δίνει . Υπάρχουν δύο περιπτώσεις:

  • Εάν τα τρία αυτά γινόμενα είναι ομόσημα, τότε μπορούμε να τα θεωρήσουμε θετικά (καθώς εάν και τα τρία είναι αρνητικά, απλά αντιστρέφουμε τη σειρά τους και αλλάζει πρόσημο το εμβαδόν, αλλά δεν μας πειράζει καθώς έχουμε απόλυτη τιμή). Στην περίπτωση αυτή, αναγκαστικά, η αρχή των αξόνων βρίσκεται μέσα στο τρίγωνο. Τότε χωρίζουμε το τρίγωνο αυτό σε τρία τρίγωνα, το τρίγωνο με άκρα , το τρίγωνο με άκρα και το τρίγωνο με άκρα . Τότε το εμβαδόν του τριγώνου θα είναι ίσο με το άθροισμα των εμβαδών των τριών τριγώνων, οπότε καταλήγουμε στον τύπο
  • Εάν δεν είναι ομόσημα, τότε όπως και πριν μπορούμε να θεωρήσουμε ότι δύο από αυτά είναι θετικά και ένα είναι αρνητικό. Χωρίς βλάβη της γενικότητας έστω ότι το τρίτο γινόμενο είναι αρνητικό. Τότε, το άθροισμα των πρώτων δύο γινομένων ισούται με το εμβαδόν του τετραπλεύρου . Για να βρούμε την απάντηση που ψάχνουμε, θέλουμε να αφαιρέσουμε το εμβαδόν του τριγώνου , το οποίο είναι ίσο με το μισό του αντίθετου του τρίτου γινομένου. Συνεπώς, το ήμισυ του αθροίσματος των τριών γινομένων ισούται με το εμβαδόν του τριγώνου, οπότε πάλι καταλήγουμε ότι

Μάλιστα, μπορούμε εύκολα να δούμε ότι το CCW ισχύει καθώς όταν αλλάζουμε τη σειρά των σημείων για να βεβαιωθούμε ότι το πρόσημο είναι θετικό, αλλάζει η σειρά από αριστερόστροφη σε δεξιόστροφη και αντίθετα.

Επιστρέφοντας στο αρχικό πρόβλημα, έστω ότι έχουμε αποδείξει ότι το εμβαδόν του πολυγώνου εάν αφαιρέσουμε το -οστό σημείο ισούται με . Πάλι, υπάρχουν δύο περιπτώσεις:

  • Εάν το βρίσκεται έξω από το πολύγωνο, τότε το τρίγωνο βρίσκεται επίσης έξω από το πολύγωνο, οπότε το συνολικό εμβαδόν του πολυγώνου ισούται με . Όμως, επειδή το βρίσκεται έξω από το πολύγωνο, τα σημεία είναι αριστερόστροφα. Συνεπώς έχουμε ότι και άρα το εμβαδόν του πολυγώνου γίνεται
  • Εάν το βρίσκεται μέσα στο πολύγωνο, τότε το τρίγωνο βρίσκεται επίσης μέσα στο πολύγωνο, οπότε το συνολικό εμβαδόν του πολυγώνου ισούται με . Όμως, επειδή το βρίσκεται μέσα το πολύγωνο, τα σημεία είναι δεξιόστροφα. Συνεπώς έχουμε ότι και άρα το εμβαδόν του πολυγώνου γίνεται

Καθώς ήδη αποδείξαμε ότι ο τύπος ισχύει για τρία σημεία, επαγωγικά μπορούμε να δούμε ότι ισχύει και για οποιαδήποτε σημεία, αφού μπορούμε να προσθέτουμε σημεία μέχρι να φτάσουμε στο .

Προβλήματα

Spoj LINESEG

Spoj VISION

Codeforces 198 Div. 2 B

Σχόλια