Robots! Collect these pickles!
Ruby, 15+26+17+26+17 = 101

Robot Finds Pickles!

Okay, here's a baseline to get people started, using the following super-naive algorithm:


Each tick, each robot will act in numeric order, performing the following steps:


Identify the closest (Manhattan distance) pickle that no other robots are targeting.
Figure out which adjacent squares are available to move to.
Choose one of those squares, preferring directions that move it closer to the selected pickle.



Here's what it looks like for Test Case #1:



Obviously this isn't very good but it's a start!

Code:

Tile = Struct.new(:world, :tile, :x, :y) do
    def passable?
        tile =~ /\.|P/
    end

    def manhattan_to other
        (self.x - other.x).abs + (self.y - other.y).abs
    end

    def directions_to other
        directions = []
        directions &lt;&lt; ?U if self.y &gt; other.y
        directions &lt;&lt; ?D if self.y &lt; other.y
        directions &lt;&lt; ?L if self.x &gt; other.x
        directions &lt;&lt; ?R if self.x &lt; other.x
        directions
    end

    def one_step direction
        nx,ny = case direction
            when ?U then [self.x, self.y - 1]
            when ?D then [self.x, self.y + 1]
            when ?L then [self.x - 1, self.y]
            when ?R then [self.x + 1, self.y]
        end

        self.world[nx,ny]
    end

    def move direction
        destination = one_step(direction)
        raise "can't move there" unless destination &amp;&amp; destination.passable?

        destination.tile, self.tile = self.tile, ?.
    end
end

class World
    DIRECTIONS = %w(U D L R)

    def initialize s
        @board = s.split.map.with_index { |l,y| l.chars.map.with_index { |c,x| Tile.new(self, c, x, y) }}
        @width = @board[0].length
    end

    def [] x,y
        y &gt;= 0 &amp;&amp; x &gt;= 0 &amp;&amp; y &lt; @board.size &amp;&amp; x &lt; @board[y].size &amp;&amp; @board[y][x]
    end

    def robots
        tiles_of_type(/[0-9]/).sort_by { |t| t.tile }
    end

    def pickles
        tiles_of_type ?P
    end

    def tiles_of_type type
        @board.flatten.select { |t| type === t.tile }
    end

    def inspect
        @board.map { |l| l.map { |t| t.tile }*'' }*?\n
    end
end

gets(nil).split("\n\n").each do |input|
    w = World.new(input)
    steps = Hash[w.robots.map { |r| [r.tile, []] }]
    while (pickles_remaining = w.pickles).size &gt; 0
        current_targets = Hash.new(0)

        w.robots.each do |r|
            target_pickle = pickles_remaining.min_by { |p| [current_targets[p], r.manhattan_to(p)] }

            possible_moves = World::DIRECTIONS.select { |d| t = r.one_step(d); t &amp;&amp; t.passable? }
            raise "can't move anywhere" if possible_moves.empty?

            direction = (r.directions_to(target_pickle) &amp; possible_moves).first || possible_moves[0]

            current_targets[target_pickle] += 1
            steps[r.tile] &lt;&lt; direction
            r.move(direction)
        end
    end

    puts steps.values.map &amp;:join
    p steps.values.map { |v| v.size }.max
end


Takes input on STDIN in exactly the format of the test case code-block in the original question.  Here's what it prints for those test cases:

DDLLDLLLLULLUUD
LDLRRDDLDLLLLDR
URDDLLLLLULLUUL
15
ULDLDDLDRRRURRURDDDDDDDLLL
UUULDDRDRRRURRURDLDDDDLDLL
ULUURURRDDRRRRUUUDDDDLDLLL
26
URRRDRUDDDDLLLDLL
RUUUDLRRDDDLLLDLL
LDRDDLDDLLLLLLLUU
RUUURDRDDLLLLLUUU
17
DULLUUUUULDLDLLLLLDDRUUUUR
UDLRRRURDDLLLUUUUURDRUUUUD
26
LDDLDUUDDDUDDDDDR
ULUULDDDDDRDRDDDR
LULLDUUDDDRDRDDDR
UUUURDUURRRRDDDDD
LDLLUDDRRRRRRUDRR
17