alz

Google Code Jam 2013 Round 1B Osmos

alz
May 4th, 2013
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.57 KB | None | 0 0
  1. '''
  2. Google Code Jam 2013 Round 1B Osmos
  3. @author: Allen
  4.  
  5. Observations:
  6. - Always add or remove the largest possible mote, and order doesn't matter
  7. - Always have Armin's mote absorb all it can, so I know when I'm done when there are no motes to be absorbed
  8. '''
  9. import os
  10.  
  11. # Perform an exhaustive search where I calculate the pairs (mote, motes) and
  12. # find the smallest number of ops = add + remove that absorbs all motes.
  13. # This is actually O(N^3) but since N <= 100 I didn't bother to optimize.
  14. def osmos(mote, motes):
  15.     # Makes it simpler and faster to add and remove the largest mote.
  16.     motes.sort()
  17.    
  18.     # The search space is a 2D array[add][remove]
  19.     # This starting value is where add = remove = 0 (i.e. do nothing)
  20.     space = [[expand(mote, motes)]]
  21.    
  22.     # The upper bound is where we remove the motes one by one
  23.     upperbound = len(space[0][0][1])
  24.    
  25.     # I search the smallest number of operations first, which guarantees that
  26.     # the first solution I find is optimal.
  27.     for ops in range(1, upperbound):
  28.         for remove in range(ops):
  29.             add = ops - remove
  30.  
  31.             if remove == 0:
  32.                 # add the largest mote possible = Armin's mote - 1, so 2*mote-1 total
  33.                 ref = space[add - 1][0]
  34.                 space.append([expand(2 * ref[0] - 1, ref[1])])
  35.             else:
  36.                 # remove the largest mote = last mote in a sorted list
  37.                 ref = space[add][remove - 1]
  38.                 space[add].append((ref[0], ref[1][:-1]))
  39.            
  40.             # found a solution!
  41.             if(len(space[add][remove][1]) == 0):
  42.                 return ops
  43.     return upperbound
  44.  
  45. # returns the equivalent representation where Armin's mote has absorbed all motes possible
  46. # precondition: motes is sorted
  47. def expand(mote, motes):
  48.     newmote = mote
  49.     bigmotes = []
  50.     for index, mote in enumerate(motes):
  51.         if(mote < newmote):
  52.             newmote += mote
  53.         else:
  54.             # Armin can't absorb the remaining motes
  55.             bigmotes = motes[index:]
  56.             break
  57.     return newmote, bigmotes
  58.  
  59. # Boilerplate code for I/O
  60. if __name__ == "__main__":
  61.     pname = 'A-example'
  62.     with open(os.path.join(os.path.dirname(__file__), pname+'.in')) as fin, open(os.path.join(os.path.dirname(__file__), pname+'.out'), 'w') as fout:
  63.         T = int(fin.readline())
  64.         for case in range(T):
  65.             mote = int(fin.readline().split()[0])
  66.             result = osmos(mote, [int(i) for i in fin.readline().split()])
  67.             fout.write("Case #{0}: {1}\n".format(case + 1, result))
Add Comment
Please, Sign In to add comment