Løsning af skyline-problemet



Relaterede dokumenter
Linear Programming ١ C H A P T E R 2

Løsning af møntproblemet

BRP Kursusintroduktion og Java-oversigt

Kursus navn: Indledende programmering Kursus nr

Help / Hjælp

Fejlbeskeder i SMDB. Business Rules Fejlbesked Kommentar. Validate Business Rules. Request- ValidateRequestRegist ration (Rules :1)

Business Rules Fejlbesked Kommentar

LUL s Flower Power Vest dansk version

Skriftlig eksamen i Datalogi

Det er muligt at chekce følgende opg. i CodeJudge: og

Hvordan vælger jeg dokumentprofilen?

PARALLELIZATION OF ATTILA SIMULATOR WITH OPENMP MIGUEL ÁNGEL MARTÍNEZ DEL AMOR MINIPROJECT OF TDT24 NTNU

Fejlbeskeder i Stofmisbrugsdatabasen (SMDB)

Intervalsøgning. Algoritmisk geometri. Motivation for intervaltræer. Intervalsøgning. Lad der være givet en database over ansatte i en virksomhed

Portal Registration. Check Junk Mail for activation . 1 Click the hyperlink to take you back to the portal to confirm your registration

Project Step 7. Behavioral modeling of a dual ported register set. 1/8/ L11 Project Step 5 Copyright Joanne DeGroat, ECE, OSU 1

Skriftlig Eksamen Beregnelighed (DM517)

how to save excel as pdf

Trolling Master Bornholm 2014

Trolling Master Bornholm 2014

Øvelse 9. Klasser, objekter og sql-tabeller insert code here

A Profile for Safety Critical Java

Tree klassen fra sidste forelæsning

Unitel EDI MT940 June Based on: SWIFT Standards - Category 9 MT940 Customer Statement Message (January 2004)

WIO200A INSTALLATIONS MANUAL Rev Dato:

User Manual for LTC IGNOU

Rekursion og dynamisk programmering

University of Southern Denmark Syddansk Universitet. DM503 Forelæsning 11

DET KONGELIGE BIBLIOTEK NATIONALBIBLIOTEK OG KØBENHAVNS UNIVERSITETS- BIBLIOTEK. Index

Basic statistics for experimental medical researchers

IBM Network Station Manager. esuite 1.5 / NSM Integration. IBM Network Computer Division. tdc - 02/08/99 lotusnsm.prz Page 1

Montageanvisning Assembly instructions. MultiDicer KMD 12, 18

Aktivering af Survey funktionalitet

Vina Nguyen HSSP July 13, 2008

Boligsøgning / Search for accommodation!

Skriftlig Eksamen Kombinatorik, Sandsynlighed og Randomiserede Algoritmer (DM528)

Dynamisk programmering

Design by Contract. Design and Programming by Contract. Oversigt. Prædikater

Noter til kursusgang 8, IMAT og IMATØ

Abstrakte datatyper C#-version

Bilag 1 Rige billeder Ordremodtagelse

StarWars-videointro. Start din video på den nørdede måde! Version: August 2012

Trolling Master Bornholm 2014

VARIO D1. Samlet pris kr. XXXX,-

Remember the Ship, Additional Work

Montage bjælkeklipper BM 5001R Art. No Assembly scythe mower BM 5001R Art. No

Engelsk. Niveau C. De Merkantile Erhvervsuddannelser September Casebaseret eksamen. og

Trolling Master Bornholm 2015

Privat-, statslig- eller regional institution m.v. Andet Added Bekaempelsesudfoerende: string No Label: Bekæmpelsesudførende

Varenr.: højre venstre º højre med coating º venstre med coating

AAU, Programmering i Java Intern skriftlig prøve 18. maj 2007

Skriftlig Eksamen Diskret matematik med anvendelser (DM72)

Programmering i C. Lektion december 2008

Modtageklasser i Tønder Kommune

Titel: Barry s Bespoke Bakery

Trolling Master Bornholm 2013

Shooting tethered med Canon EOS-D i Capture One Pro. Shooting tethered i Capture One Pro 6.4 & 7.0 på MAC OS-X & 10.8

Noter til kursusgang 9, IMAT og IMATØ

DATALOGI 0GB. Skriftlig eksamen tirsdag den 6. januar 2004

Transport af lithiumbatterier i undtagne mængder med TNT Express (gældende fra January 1, 2010)

28 Algoritmedesign. Noter. PS1 -- Algoritmedesign

University of Southern Denmark Syddansk Universitet. DM502 Forelæsning 2

Vores mange brugere på musskema.dk er rigtig gode til at komme med kvalificerede ønsker og behov.

To the reader: Information regarding this document

Titel: Hungry - Fedtbjerget

Podia samlevejledning

Transkript:

Løsning af skyline-problemet Keld Helsgaun RUC, oktober 1999 Efter at have overvejet problemet en stund er min første indskydelse, at jeg kan opnå en løsning ved at tilføje en bygning til den aktuelle skyline en ad gangen. Jeg skal blot finde en repræsentation af den aktuelle skyline, som muliggør dette. Jeg vil opfatte en skyline som en liste af rektangler med en venstre x-koordinat, en højde, og en højre x-koordinat. Listen skal være ordnet således, at et rektangels venstre x-koordinat altid er større end eller lig med et eventuelt foregående rektangels højre x-koordinat. Min erfaring siger mig, at det nok vil være en god ide også at lade rektangler, hvis højde er 0, være repræsenteret i listen. Dermed er der ingen særtilfælde. Fra starten skal skylinen derfor bestå af et enkelt rektangel - med højde 0 og med venstre og højre x-koordinat lig med henholdsvis bygningernes minimale og maksimale x-koordinat. Herefter er algoritmen simpel. Jeg skal blot for hver bygning løbe den aktuelle skyline igennem og justere denne passende. Der opstår en række tilfælde, når en bygning overlapper et rektangel i skylinen, men det skulle nok være til at håndtere. For at lette programmeringen anvender jeg mig af Java-pakken simset, en pakke til håndtering af tovejslister, som jeg har tidligere udviklet (pakken er tilgængelig fra kursets hjemmeside). En kommenteret version af det udviklede Java-program ses nedenfor. For at forstå programmet er det en god ide at tegne de situationer, der kan opstå. De 4 tilfælde, der hentydes til i kommentarerne er følgende:

2 Tilfælde 1: s b Tilfælde 2: b s Tilfælde 3: b s Tilfælde 4: b s

3 import simset.*; import IO.*; //* An object of class Rectangle is used to represent a building //* or an element of the current skyline. L and R denote the //* left and right x coordinate, respectively. H is the height. //* Rectangle is a subclass of class Link of the simset package. //* Thus objects of the class can be kept in a list. class Rectangle extends Link { double L, H, R; Rectangle(double l, double h, double r) { L = l; H = h; R = r; public class SkylineProblem { public static void main(string args[]) { // Create a list of buildings Head buildings = new Head(); new Rectangle( 1, 11, 5).into(buildings); new Rectangle( 2, 6, 7).into(buildings); new Rectangle( 3, 13, 9).into(buildings); new Rectangle(12, 7, 16).into(buildings); new Rectangle(14, 3, 25).into(buildings); new Rectangle(19, 18, 22).into(buildings); new Rectangle(23, 13, 29).into(buildings); new Rectangle(24, 4, 28).into(buildings); // Find the minimum and maximum x coordinate of the // buildings double minl = Double.MAX_VALUE, maxr = Double.MIN_VALUE; for (Rectangle b = (Rectangle) buildings.first(); b!= null; b = (Rectangle) b.suc()) { if (b.l < minl) minl = b.l; if (b.r > maxr) maxr = b.r; // Create the initial skyline // (a list of Rectangle objects) Head skyline = new Head(); new Rectangle(minL, 0, maxr).into(skyline);

4 // For each building b for (Rectangle b = (Rectangle) buildings.first(); b!= null; b = (Rectangle) b.suc()) { // For each rectangle s in the current skyline for (Rect s = (Rectangle) skyline.first(); s!= null; s = (Rectangle) s.suc()) { if (b.h > s.h && s.r > b.l && s.l < b.r) { // b is higher than s and its base line // overlaps the base line of s. // There are 4 cases: if (s.l < b.l) { if (s.r <= b.r) // (1) b overlaps the right part of s. // Let a new skyline rectangle of // height b.h follow s: new Rectangle(b.L, b.h, s.r). follow(s); else { // (2) s overlaps b totally. // Split s into three rectangles: new Rectangle(b.R, s.h, s.r). follow(s); new Rectangle(b.L, b.h, b.r). follow(s); // Adjust the right x coordinate of s. s.r = b.l; else if (s.r <= b.r) // (3) b is "inside" s. s.h = b.h; else { // (4) b overlaps the right part of s. // Let a new skyline rectangle of // height s.h follow s: new Rectangle(b.R, s.h, s.r).follow(s); // Adjust the height and right // coordinate of s. s.h = b.h; s.r = b.r; // For efficiency: collapse s with its // predecessor if it has the same height: Rectangle t = (Rectangle) s.pred(); if (t!= null && t.h == s.h) { t.r = s.r; s.out(); s = t;

5 // Print the solution: for (Rectangle r = (Rectangle) skyline.first(); r!= null; r = (Rectangle) r.suc()) IO.print(r.L + " " + r.h + " "); Rectangle r = (Rectangle) skyline.last(); if (r!= null) IO.print(r.R + " " + 0); IO.println(); Programmet er korrekt, men det er ikke særligt effektivt. I det værste tilfælde kræver det O(n) skridt for at placere den n te by i skylinen. Dermed bliver det totale antal skridt lig med O(n) + O(n-1) +... + O(1) = O(n 2 ). For at forbedre effektiviteten kan del-og-hersk-teknikken benyttes. Hvert problem opdeles i to (næsten) lige store dele, som løses hver for sig, hvorefter de to løsninger samles til én løsning. Dette princip benyttes rekursivt. I dette problem kan mængden af bygninger opsplittes i to mængder, hver bestående af cirka n/2 bygninger. Derefter bestemmes de to skylines for hver af de to mængder, hvorefter de derved fremkomne skylines flettes til en skyline. To skylines kan flettes efter samme princip som i det forrige program. De to skylines gennemløbes fra venstre mod højre, idet x-koordinaterne sammenholdes, og højderne justeres, når det er nødvendigt. Nedenfor ses en udgave af et program, der benytter denne metode. Det kan vises, at køretiden er O(nlogn).

6 import simset.*; import IO.*; //* An object of class Rectangle is used to represent a building //* or an element of the current skyline. L and R denote the //* left and right x coordinate, respectively. //* H is the height. Rectangle is a subclass of class Link of //* the simset package. //* Thus objects of the class can be kept in a list. class Rectangle extends Link { double L, H, R; Rectangle(double l, double h, double r) { L = l; H = h; R = r; //* An object of class RectangleList is used to represent a list //* of buildings or a the current skyline. RectangleList is a //* subclass of class Head of the simse package. //* Thus objects of the class can used as list headers. class RectangleList extends Head { //* split() is used to split this list into two lists of //* (almost) equal length. //* The first n/2 elements of the list, where n is the //* original list length, are moved to a new list. //* This new list is the return value of split(). RectangleList split() { RectangleList L = new RectangleList(); for (int n = cardinal()/2; n > 0; n--) first().into(l); return L; //* merge(l) is used to merge two skylines. //* The skyline represented by "this" is merged by the //* skyline represented by L. The result is stored in //* "this". //* At entry "this" list should not be empty. void merge(rectanglelist L) { Rectangle s1 = (Rectangle) first(); Rectangle s2 = (Rectangle) L.first(); // Assure that all rectangles i L are fully contained in // the union of rectangles og "this": if (s2!= null) { if (s2.l < s1.l) new Rectangle(s2.L, 0, s1.l).precede(s1); s1 = (Rectangle) last(); s2 = (Rectangle) L.last(); if (s2.r > s1.r) new Rectangle(s1.R, 0, s2.r).follow(s1); s1 = (Rectangle) first(); s2 = (Rectangle) L.first();

7 // For each rectangle s2 in L: while (s2!= null) { if (s1.r <= s2.l) // Move to next rectangle in "this" list: s1 = (Rectangle) s1.suc(); else if (s2.r <= s1.l) // Move to next rectangle in L: s2 = (Rectangle) s2.suc(); // Otherwise, treat the following 4 cases: else if (s2.l <= s1.l) { if (s1.r <= s2.r) { // Case 1: s2 overlaps s1 totally if (s2.h > s1.h) { s1.h = s2.h; Rectangle t = (Rectangle) s1.pred(); if (t!= null && t.h == s1.h) { t.r = s1.r; s1.out(); s1 = t; if (s2.r == s1.r) s2 = (Rectangle) s2.suc(); s1 = (Rectangle) s1.suc() else { // Case 2: s2 overlaps the left part of s1 if (s2.h > s1.h) { new Rectangle(s2.R, s1.h, s1.r). follow(s1); s1.r = s2.r; s1.h = s2.h; Rectangle t = (Rectangle) s1.pred(); if (t!= null && t.h == s1.h) { t.r = s1.r; s1.out(); s1 = t; s2 = (Rectangle) s2.suc(); else if (s1.r < s2.r) { // Case 3: s1 overlaps the right part of s1 if (s2.h > s1.h) { new Rectangle(s2.L, s2.h, s1.r).follow(s1); s1.r = s2.l; s1 = (Rectangle) s1.suc(); else { // Case 4: s2 is contained in s1 if (s2.h > s1.h) { new Rectangle(s2.R, s1.h, s1.r).follow(s1); new Rectangle(s2.L, s2.h, s2.r).follow(s1); s1.r = s2.l; s2 = (Rectangle) s2.suc();

8 public class SkylineProblem { //* Solve the problem by divide-and-conquer static RectangleList solve(rectanglelist L1) { if (L1.first()!= L1.last()) { // More than one element in L1. RectangleList L2 = L1.split(); solve(l1); solve(l2); L1.merge(L2); return L1; public static void main(string args[]) { // Create a list of buildings: RectangleList buildings = new RectangleList(); new Rectangle( 1, 11, 5).into(buildings); new Rectangle( 2, 6, 7).into(buildings); new Rectangle( 3, 13, 9).into(buildings); new Rectangle(12, 7, 16).into(buildings); new Rectangle(14, 3, 25).into(buildings); new Rectangle(19, 18, 22).into(buildings); new Rectangle(23, 13, 29).into(buildings); new Rectangle(24, 4, 28).into(buildings); // Solve the problem: RectangleList skyline = solve(buildings); // Print the solution: for (Rectangle r = (Rectangle) skyline.first(); r!= null; r = (Rectangle) r.suc()) IO.print(r.L + " " + r.h + " "); Rectangle r = (Rectangle) skyline.last(); if (r!= null) IO.print(r.R + " " + 0); IO.println();