DDD Runde 2, 2015 – Facitliste Søren Dahlgaard og Mathias Bæk Tejs Knudsen Opgaver og løsninger til 2. runde af DDD 2015. 1 Dansk Datalogi Dyst 2015 DDD Runde 2 4.–19. februar, 2015 linetest • DK • v1.0 Line Test Sigurd er begyndt i gymnasiet og har lært om linjer p˚ a formen f (x) = ax + b. Han har prøvet at tegne nogle linjer p˚ a papir for at finde ud af hvilke koordinater der ligger under linjen, over linjen og p˚ a linjen. p1 Sigurd er dog blevet træt af at tegne, s˚ a han vil gerne have hjælp af dig til at lave et program der kan afgøre det. Heldigvis for dig er Sigurd kun interesseret i heltal. Opgave p2 Givet linjen ax + b og et heltal y skal du afgøre om ax + b < y, ax + b > y eller ax + b = y. Input En enkelt linje best˚ aende af 4 heltal: a, x, b, y i den rækkefølge. (0,0) Output En linje med teksten UNDER hvis ax + b > y, OVER hvis ax + b < y og LINJE hvis ax + b = y. Eksempler Input Output Kommentarer 1 2 3 5 LINJE 1 · 2 + 3 = 5, s˚ a punktet (2, 5) ligger p˚ a linjen. Input Output 1 2 3 4 UNDER Input Output 3 4 -10 50 OVER Pointgivning Delopgave 1 (70 point): −104 ≤ a, x, b ≤ 104 og −109 ≤ y ≤ 109 . Delopgave 2 (30 point): −108 ≤ a, x, b ≤ 108 og −1017 ≤ y ≤ 1017 . Side 1 af 2 Dansk Datalogi Dyst 2015 4.–19. februar, 2015 DDD Runde 2 linetest • DK • v1.0 Begrænsninger Tidsbegrænsning: 1 s. Hukommelsesbegrænsning: 256 MB. Side 2 af 2 1 Løsning Linetest kan løses ved at læse de 4 tal og udføre beregningerne som beskrevet i opgaven. Dette er gjort i følgende Python kode: 1 a ,x ,b , y = map ( int , raw_input () . split () ) 2 3 4 5 6 7 8 9 y2 = a * x + b if y2 < y : print " OVER " elif y2 > y : print " UNDER " else : print " LINJE " 4 Dansk Datalogi Dyst 2015 4.–19. februar, 2015 DDD Runde 2 urdisplay • DK • v1.1 Ur Display Sigurd har fundet et display, der er netop 7 × 9 felter, som han gerne vil programmere til at vise et to-cifret tal med en fin ramme. Hvert felt p˚ a displayet kan vise enten ingenting eller et af følgende tegn #, +, -, |. Sigurd har fundet ud af at han kan vise et tal ved at bruge 5 × 3 felter som det ses herunder: ### # # # # # # ### # # # # # ### ### # # ### # # # # # ### ### ### ### # # # # ### ### # ### ### ### ### ### # # # # # # ### # ### ### # # # # # # ### # ### ### Til rammen vil han bruge +, -, | og s˚ a vil han gerne have et mellemrum mellem de to cifre. Hvis han f.eks. vil vise tallet 18 ser det s˚ aledes ud: +-------+ | # ###| | # # #| | # ###| | # # #| | # ###| +-------+ Bemærk, at der er to blanke kolonner foran 1-tallet da alle tal fylder netop tre kolonner. Det kan dog ske at en af kolonnerne i displayet ikke virker, og I det tilfælde vil Sigurd ikke skrive noget til den kolonne. Hvis f.eks. d. 3. kolonne ikke virker, og Sigurd vil vise tallet 31, vil det se s˚ aledes ud: +|# | |# | |# +- -----+ # #| # #| # #| # #| # #| -----+ Alts˚ a skrives hverken ramme eller midterste kolonne af 3-tallet ud. Sigurd har bedt dig om hjælp til at skrive et program der læser et to-cifret tal og udskriver det med 7 × 9 tegn som det ville se ud p˚ a displayet. Side 1 af 3 Dansk Datalogi Dyst 2015 Opgave DDD Runde 2 4.–19. februar, 2015 urdisplay • DK • v1.1 Givet et tal samt hvilken kolonne der ikke virker skal du udskrive hvordan displayet skal se ud. Input En enkelt linje med 2 tal: Først det to-cifrede tal 10 ≤ n ≤ 99, der skal skrives ud. Dernæst et tal 0 ≤ C ≤ 8 der indikerer hvilken kolonne der ikke virker. C = 0 betyder at alle kolonner virker. Bemærk at den sidste kolonne (kolonne 9) altid virker! Output 7 linjer hver best˚ aende af 9 tegn som forestiller displayet som beskrevet herover. Eksempler Input Output Kommentarer 18 0 +-------+ | # ###| | # # #| | # ###| | # # #| | # ###| +-------+ Se forklaring i opgavebeskrivelsen Input Output Kommentarer 31 3 +|# | |# | |# +- Se forklaring i opgavebeskrivelsen -----+ # #| # #| # #| # #| # #| -----+ Side 2 af 3 Dansk Datalogi Dyst 2015 DDD Runde 2 4.–19. februar, 2015 Input Output 99 1 Kommentarer urdisplay • DK • v1.1 Bemærk at der stadig skrives en blank kolonne ud i starten. Alts˚ a indeholder hver linje netop 9 tegn. -------+ ### ###| # # # #| ### ###| # #| ### ###| -------+ Pointgivning Delopgave 1 (50 point): C = 0. Delopgave 2 (50 point): 0 ≤ C ≤ 8. Begrænsninger Tidsbegrænsning: 1 s. Hukommelsesbegrænsning: 256 MB. Side 3 af 3 2 Løsning I urdisplay skal vi bygge den tekst vi vil skrive ud. Dette kan f.eks. gøres ved at gemme de forskellige tal i en liste eller et array, og indeksere ind i denne. Husk at tage højde for den kolonne, der ikke skal udskrives! 1 2 3 4 5 6 7 8 9 10 digits = [[ " ### " , [" #", [ " ### " , [ " ### " , ["# #", [ " ### " , [ " ### " , [ " ### " , [ " ### " , [ " ### " , "# " " " "# "# "# " "# "# #", #", #", #", #", ", ", #", #", #", "# #", " #", " ### " , " ### " , " ### " , " ### " , " ### " , " #", " ### " , " ### " , "# " "# " " " "# " "# " #", #", ", #", #", #", #", #", #", #", " ### " ] , " #"], " ### " ] , " ### " ] , " #"], " ### " ] , " ### " ] , " #"], " ### " ] , " ### " ]] #0 #1 #2 #3 #4 #5 #6 #7 #8 #9 11 12 n , C = map ( int , raw_input () . split () ) 13 14 15 a = ( n /10) b = n %10 16 17 18 19 20 21 out = [ " " for x in range (7) ] out [0] = " + - - - - - - -+ " out [6] = " + - - - - - - -+ " for i in range (1 ,6) : out [ i ] = " | " + digits [ a ][ i -1] + " " + digits [ b ][ i -1] + " | " 22 23 24 25 if C != 0: for i in range (0 ,7) : out [ i ] = out [ i ][:( C -1) ]+ " " + out [ i ][ C :] 26 27 28 for i in range (0 ,7) : print out [ i ] 8 Dansk Datalogi Dyst 2015 Lejrtur DDD Runde 2 4.–19. februar, 2015 lejrtur • DK • v1.1 Sigurds klasse er taget p˚ a lejrtur, men under et natløb er Sigurd faret vild, og han er nødt til at krydse en stor flod for at komme hjem. Sigurd har heldigvis fundet en 30m lang planke, som han kan bruge som bro til at krydse floden. I floden er der et antal sm˚ a øer som Sigurd netop kan st˚ a p˚ a sammen med sin planke. Sigurds plan er at bruge planken som bro til at n˚ a en ø, og s˚ a flytte planken og bruge den som bro til at n˚ a en ny ø indtil han er n˚ aet over p˚ a den anden side. Inden han begynder vil han dog godt have at vide om det overhovedet kan lade sig gøre givet placeringerne af øerne. L W Figure 1: Et eksempel hvor Sigurd har brugt planken til at bevæge sig over floden i venstre side. Opgave Givet flodens bredde, længde og placeringen af øerne skal du afgøre om det er muligt for Sigurd at komme over p˚ a den anden siden ved hjælp af sin planke. Input Den første linje indeholder tre heltal L, W og n, som er hhv. længden og bredden af floden og antallet af øer som Sigurd kan bruge til at komme over p˚ a den anden side. De næste n linjer indeholder hver to heltal 0 ≤ x ≤ L og 0 ≤ y ≤ W som er positionen af en ø i floden. Floden g˚ ar fra koordinat (0, 0) til (L, W ). Koordinat (0, 30) svarer til en ø 30m ude i vandet helt i venstre side af floden. Sigurds planke er altid 30m lang. Det vil altid gælde, at 1 ≤ L, W ≤ 104 . Side 1 af 2 Dansk Datalogi Dyst 2015 Output DDD Runde 2 4.–19. februar, 2015 lejrtur • DK • v1.1 En enkelt linje med teksten SUCCES hvis det er muligt for Sigurd at n˚ a den anden side eller teksten FORTABT hvis det ikke kan lade sig gøre. Eksempler Input Output Kommentarer 10 60 1 0 30 SUCCES Sigurd kan lige netop n˚ a ud til øen og lige netop n˚ a fra øen i land p˚ a den anden side (begge afstande er 30m). Input Output Kommentarer 10 61 1 0 30 FORTABT Her er afstanden fra øen til den anden side for lang (31m), s˚ a Sigurd kan ikke n˚ a over floden. Input Output Kommentarer 30 70 2 10 30 20 40 SUCCES Sigurd g˚ ar først ud til ø nummer 1, som ligger 30m fra land. S˚ a g˚ ar han fra ø nummer 1 til nummer 2 og s˚ a i land p˚ a den anden side. Bemærk, at afstanden fra ø nummer 1 til ø √ nummer 2 er mindre end 30 (nemlig 10 2m), men det er ikke noget problem. Pointgivning Delopgave 1 (20 point): 1 ≤ n ≤ 5000. Alle øer har samme x-koordinat. Delopgave 2 (80 point): 1 ≤ n ≤ 5000. Begrænsninger Tidsbegrænsning: 1 s. Hukommelsesbegrænsning: 256 MB. Side 2 af 2 3 Løsning Lejrtur kan ses som en klassisk anvendelse af flood fill : Vi holder styr på om vi har været ved hver ø. Når vi besøger en ny ø finder vi alle øer inden for 30 meters afstand og besøger dem rekursivt. For 20 point er det nok, at sortere øerne efter y-koordinat og se om denne rækkefølge kan nå fra den ene til den anden side uden afstande over 30m. 1 2 def distSq (x , y ) : return x * x + y * y 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 L ,W , n = map ( int , raw_input () . split () ) xs = [0 for i in range ( n ) ] ys = [0 for i in range ( n ) ] for i in range ( n ) : xs [ i ] , ys [ i ] = map ( int , raw_input () . split () ) visited = [ False for i in range ( n ) ] toVisit = [] for i in range ( n ) : if ys [ i ] <= 30: toVisit . append ( i ) visited [ i ] = True while len ( toVisit ) > 0: i = toVisit . pop () for j in range ( n ) : if ( not visited [ j ]) and distSq ( xs [ i ] - xs [ j ] , ys [ i ] - ys [ j ]) <= 30*30: toVisit . append ( j ) visited [ j ] = True success = False for i in range ( n ) : if visited [ i ] and ys [ i ] >= W -30: success = True if success : print " SUCCES " else : print " FORTABT " 11 Dansk Datalogi Dyst 2015 DDD Runde 2 4.–19. februar, 2015 temperatur • DK • v1.1 Temperatur Sigurd har f˚ aet en hjemmeopgave, hvor de skal analysere temperaturen i løbet af ˚ aret. Sigurd har besluttet, at han gerne vil undersøge mediantemperaturen i løbet af ˚ aret. Medianen af n tal er den midterste værdi, hvis n er ulige, og gennemsnittet af de to midterste værdier, hvis n er lige. F.eks. er medianen af (1, 3, 5, 8, 8) lig med 5, og medianen af (1, 4, 4, 5, 6, 7) er 4.5. For at undersøge mediantemperaturen har Sigurd bygget en temperaturm˚ aler, som giver ham en temperatur om dagen. Hver dag kunne Sigurd godt tænke sig at vide hvad mediantemperaturen har været siden han startede med at m˚ ale. Til det har han opsøgt dig for at finde hjælp. Opgave Givet temperaturerne for alle de dage Sigurd har foretaget m˚ alinger skal du beregne medianen for m˚ alingerne fra starten til hver enkelt dag. Input Første linje indeholder et heltal n, som er antallet af dage. Herefter følger n linjer, som hver best˚ ar af en m˚ aling i form af et heltal ai . Den i’te linje svarer til m˚ alingen p˚ a den i’te dag. −109 ≤ ai ≤ 109 Output For hver af de n m˚ alinger ai skal du skrive en linje med medianen af de første i m˚ alinger (a1 , . . . , ai ). Output skal være i samme rækkefølge som input. Eksempler Input Output Kommentarer 5 4 3 1 8 6 4 3.5 3 3.5 4 Medianen af 4 er 4 Medianen af (4, 3) er (4 + 3)/2 = 3.5 Medianen af (1, 3, 4) er 3 osv. Side 1 af 2 Dansk Datalogi Dyst 2015 4.–19. februar, 2015 Input Output 6 1000 998 -1000 5 3 5 1000 999 998 501.5 5 5 DDD Runde 2 temperatur • DK • v1.1 Pointgivning Delopgave 1 (50 point): 1 ≤ n ≤ 1000 Delopgave 2 (50 point): 1 ≤ n ≤ 200000 Begrænsninger Tidsbegrænsning: 5 s. Hukommelsesbegrænsning: 256 MB. Side 2 af 2 4 Løsning For 50 point i temperatur er det tilstrækkeligt, at sortere alle tallene hver gang man læser et nyt. I listen af sorterede tal er det nemt at finde medianen hurtigt. For fuld point kan man enten bruge en træstruktur eller en prioritetskø (http://en.wikipedia. org/wiki/Priority_queue). I prioritetskø-løsningen vil man have to køer: En til den største halvdel af tal og en til den laveste halvdel. For at finde medianen skal vi nu blot kigge på det største tal i den laveste halvdel og det mindste tal i den største halvdel. 1 import heapq 2 3 4 5 def solve ( n ) : lo = [] hi = [] 6 7 8 9 10 11 12 13 14 15 16 # First handle cases n = 1 ,2 to make the loop easier cause I ’m a bad # programmer . a = int ( raw_input () ) print a if n == 1: return b = int ( raw_input () ) print ( a + b ) *0.5 lo = [ min (a , b ) * -1] hi = [ max (a , b ) ] 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 for i in range (2 , n ) : a = int ( raw_input () ) if i %2 == 0: # Odd number . Add to lo b = heapq . heappop ( hi ) heapq . heappush ( lo , min (a , b ) * -1) heapq . heappush ( hi , max (a , b ) ) x = heapq . heappop ( lo ) print -x heapq . heappush ( lo , x ) else : b = - heapq . heappop ( lo ) heapq . heappush ( lo , min (a , b ) * -1) heapq . heappush ( hi , max (a , b ) ) x1 , x2 = heapq . heappop ( lo ) , heapq . heappop ( hi ) print ( - x1 + x2 ) *0.5 heapq . heappush ( lo , x1 ) heapq . heappush ( hi , x2 ) 35 36 37 38 solve ( int ( raw_input () ) ) 14 Dansk Datalogi Dyst 2015 Trekant 4.–19. februar, 2015 DDD Runde 2 trekant • DK • v1.3 Sigurds lærer har givet sigurd en mængde af n punkter i planen og bedt Sigurd om at finde arealet af den største trekant udspændt af tre af punkterne. Dette er illustreret i Figur 1. Dette kan Sigurd dog ikke finde ud af, og han vil gerne bede dig om hjælp. Figure 1: Eksempel af 7 punkter i planen og den størst udspændte trekant markeret. Opgave Givet n punkter i planen skal du beregne arealet1 af den største trekant udspændt af tre af punkterne. Input Den første linje indeholder et heltal n, der er antallet af punkter. De næste n linjer indeholder hver to heltal x, y som er hhv. x og y koordinatet af et af punkterne. Det gælder, at −104 ≤ x, y ≤ 104 . Output En linje med arealet af den største trekant. Dit svar skal have en absolut præcision p˚ a 10−6 −6 (dvs. højest være 10 fra det rigtige svar). Bemærk at der godt kan være mere end en trekant med størst areal. Eksempler 1 Se f.eks. http://en.wikipedia.org/wiki/Triangle#Computing_the_area_of_a_triangle Side 1 af 2 Dansk Datalogi Dyst 2015 DDD Runde 2 4.–19. februar, 2015 trekant • DK • v1.3 Input Output Kommentarer 4 1 1 6 6 12.5 Den største trekant (1, 1), (6, 1), (6, 6) Input Output Kommentarer 4 1 2 3 3 1 Bemærk, at det er okay hvis dit program skriver 1.0, 1.0000 eller lignende. 1 5 1 6 1 2 3 4 Input Output 4 1 1 1 4 13.5 1 1 10 5 Pointgivning Delopgave 1 (75 point): 3 ≤ n ≤ 100. Delopgave 2 (25 point): 3 ≤ n ≤ 5000. Begrænsninger Tidsbegrænsning: 1 s. Hukommelsesbegrænsning: 256 MB. Side 2 af 2 er punkterne 5 Løsning For at få 75 point er det nok at loope over samtlige 3 punkter i sættet og finde de 3 punkter der udgør den største trekant. For at få fuld point skal man først finde det konvekse hylster af punkterne (http://en.wikipedia. org/wiki/Convex_hull). Vi skal derefter finde den største trekant udspændt af tre punkter på det konvekse hylster. Bemærk, at der kan være mange punkter på det konvekse hylster, så vi kan ikke bare prøve alle trekanter. Der er mange måder at gøre det effektivt dog. En måde er at fastsætte to punkter og finde det tredje ved hjælp af en ternary search. Dette kan vi gøre, fordi arealet af trekanten givet det tredje punkt er en unimodal funktion, hvis vi kigger på punkterne der ligger mellem de to fastsatte punkter på det konvekse hylster. En anden, og måske nemmere måde, kan læses på følgende link: http://stackoverflow.com/ a/1621913. Denne løsning er implementeret i koden herunder. 1 2 # Better O ( n ^2) algorithm . Should get full points . Note that the rotating # calipers part can be done in O ( n ) time as well . 3 4 5 6 # Cross product def cross (o , a , b ) : return ( a [0] - o [0]) * ( b [1] - o [1]) - ( a [1] - o [1]) * ( b [0] - o [0]) 7 8 9 10 11 12 # Convex Hull . Taken from wikibooks def convex_hull ( points ) : points = sorted ( set ( points ) ) if len ( points ) <= 1: return points 13 14 15 16 17 18 19 # Build lower hull lower = [] for p in points : while len ( lower ) >= 2 and cross ( lower [ -2] , lower [ -1] , p ) <= 0: lower . pop () lower . append ( p ) 20 21 22 23 24 25 26 # Build upper hull upper = [] for p in reversed ( points ) : while len ( upper ) >= 2 and cross ( upper [ -2] , upper [ -1] , p ) <= 0: upper . pop () upper . append ( p ) 27 28 return lower [: -1] + upper [: -1] 29 30 31 32 # Area of triangle def area ( p1 , p2 , p3 ) : return 0.5 * abs ( cross ( p1 , p2 , p3 ) ) 33 34 35 36 37 38 n = int ( raw_input () ) p = [0]* n for i in range ( n ) : x , y = map ( int , raw_input () . split () ) p [ i ] = (x , y ) 39 40 h = convex_hull ( p ) 17 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 n = len ( h ) best = 0 # Rotating calipers for a in range ( n ) : b = ( a +1) % n c = ( a +2) % n while True : while ( area ( h [ a ] , h [ b ] , h [( c +1) % n ]) >= area ( h [ a ] , h [ b ] , h [ c ]) ) : c = ( c +1) % n if ( area ( h [ a ] , h [( b +1) % n ] , h [ c ]) >= area ( h [ a ] , h [ b ] , h [ c ]) ) : b = ( b +1) % n continue else : break 56 57 best = max ( best , area ( h [ a ] , h [ b ] , h [ c ]) ) 58 59 print best 18
© Copyright 2024