Pattern matching in the first pattern had nothing to do with greedyness. It matched <tr> followed by 0 to 200 characters of any kind (dot_all pattern modifier) followed by one of the three words another 0 to 200 characters and </tr>, and [0][0] contains the whole pattern match. One way to NOT match the first characters would be
$p = '#<tr>\s*<td>(Bedroom|...#isu';
Since it would only allow white space between tr and td, while the first row contains th instead of td. Or you could start the pattern with
$p = '#</tr>\K';
An example of greedyness functionality
$text = '
<tr>
<td>one</td>
<td>two</td>
<td>three</td>
</tr>
</table>';
preg_match_all('#one.*</td>#sU',$text,$match);
echo '<b>Ungreedy</b><pre>';
echo htmlentities(print_r($match,1));
echo '</pre>';
preg_match_all('#one.*</td>#s',$text,$match);
echo '<b>Greedy</b><pre>';
echo htmlentities(print_r($match,1));
echo '</pre>';
As the example shows, a greedy match will match the maximum amount of characters possible while the rest of the pattern still matches. Ungreedy means matching the least amount of characters possible while the rest of the pattern still matches.