-- ACM Pacific NW Region Programming Contest, 11 November 2000 -- Problem F, Radio Transmitter -- Sergio Antoy -- Fri Nov 30 13:14:28 PST 2001 -- updated: Mon Sep 23 15:22:15 PDT 2002 import Read prettyPrint base power = putStrLn ("Add a power " ++ show power ++ " transmitter at " ++ show i ++ "," ++ show j) where (i,j) = find indices find ((i,j):ijs) = if all (>= 100) newbase then (i,j) else find ijs where newbase = addSignal base (i,j,power) addSignal base xyz = accum base indices where accum [] [] = [] accum (b:bs) (ij:ijs) = (b + strength xyz ij) : accum bs ijs findTransmitter base (high,low) -- invariant: low < power <= high = if high==low+1 then prettyPrint base high else findTransmitter base if couldBeLower then (middle,low) else (high,middle) where middle = (high+low) `div` 2 couldBeLower = any (== True) (map (\(x,y) -> (acceptable (addSignal base (x,y,middle)))) indices) acceptable bs = all (>= 100) bs doOne p = if all (>= 100) base then putStrLn "No additional transmitter needed" else findTransmitter base (highest,0) where base = map (accum p) indices accum [] _ = 0 accum (xyz:ts) ij = accum ts ij + strength xyz ij strength (x,y,z) (i,j) = z `div` if i==x && j==y then 1 else (i-x)*(i-x) + (j-y)*(j-y) highest = 80000 -- 80000 `div` 2*(20^2) >= 100 indices = [(i,j) | i <- [-10..10], j <- [-10..10]] doAll t = if one==[] then return () else doOne one >> doAll rest where (one,rest) = accum t accum (x:y:z:t) | z==0 = ([],t) | otherwise = let (u,v) = accum t in ((x,y,z):u,v) main = do input <- readFile "f.dat" doSolve (input=:=input) doAll (map readInt (words input))