My approach - standard backtrack.  
I represented the board as a 15 by 21 rectangle, and the two
types of cells (parity) as 0 and 1.  For each orientation of 
each piece, I had to track the locations of the cells it would 
fill, and also their parity.  I followed a set scanning order, 
going across the rows, bottom to top, from right to left, find 
the first unfilled cell, scan the randomized list of pieces and 
orientations to find the next piece of proper parity which would 
fit, and testing to see if holes were created, and also if the 
piece touched the top, to see that any regions created were not 
divisible by 5.  When no more placements were possible, lift 
the last piece and continue.

Occasionally a region would occur which was fillable only by 
pieces already in place.  The solver would spin its wheels trying 
to fill the rest of that row, hitting the bad place, then 
backtracking. If this happened early on, too much time would be 
required to backtrack far enough due to the larger number of 
possibilities.  I decided not to program a check for this, since 
most of the time the solver ran very quickly up to the 57-59 
pieces placed range, and getting past bad areas was very fast 
due to the small number of pieces left to try.  Also each time 
I restarted, the run was different due to the randomization.

    Source: geocities.com/liviozuc/download

               ( geocities.com/liviozuc)