(追記)コードを眺めていたら、初期処理部分はばっさり消せることに気づきました。
新しいコードを置いておきます。

<?php
// 自分の得意な言語で
// Let's チャレンジ!!
$s = explode(" ",trim(fgets(STDIN)));
$h = $s[0];
$w = $s[1];
$l_num = $s[2];
$con = 0;//reset カウント
$hatena_flag = false;// ?にしたかどうか
//map取得
for ($i = 0; $i < $h; $i++) {
$hoge = trim(fgets(STDIN));
for ($j = 0; $j < $w; $j++) {
$map[$i][$j] = mb_substr($hoge, $j, 1);
if($map[$i][$j]=="*"){
$y = $i;
$x = $j;
}
}
}
//l取得
for ($i = 0; $i < $l_num; $i++) {
$hatena[] = trim(fgets(STDIN));
}
//print_r($hatena);
//初期位置に関して
if($hatena[0] == $con){
$map[$y][$x] = "?";
array_shift($hatena);
}else{
$map[$y][$x] = "*";
}
$newstar[]=array($y,$x, $con);
$con++;
//print_r($map);
while(count($newstar)>=1){//移動可能な配列がある限り続ける
$y = $newstar[0][0];
$x = $newstar[0][1];
$con = ($newstar[0][2])+1;
//?にするところかどうか
for($i=0; $i<count($hatena); $i++){
if($con == $hatena[$i]){
$hatena_flag = true;
}
}
if($hatena_flag == true){
$put_text="?";
}else{
$put_text="*";
}
//共通操作
if($y>=1 && $map[$y-1][$x]=="."){
$map[$y-1][$x] =$put_text;
$newstar[]=array($y-1,$x, $con);
}
if($y<$h-1 && $map[$y+1][$x]=="."){
$map[$y+1][$x] = $put_text;
$newstar[]=array($y+1,$x, $con);
}
if($x>=1 && $map[$y][$x-1]=="."){
$map[$y][$x-1] = $put_text;
$newstar[]=array($y,$x-1, $con);
}
if($x<$w-1 && $map[$y][$x+1]=="."){
$map[$y][$x+1] = $put_text;
$newstar[]=array($y,$x+1, $con);
}
array_shift($newstar);//いまつかった配列を消す
//print_r($newstar);
$hatena_flag = false;
}
//出力
for ($i = 0; $i < $h; $i++) {
for ($j = 0; $j < $w; $j++) {
echo($map[$i][$j]);
}
echo("\n");
}
?>
すっきりしました。
(以下は修正前のコードです。参考にはなりません。あしからず)
くたくたなのでコードだけ置いておきます。
ご参考になるかどうか。
ここまでくると、コードが正しいかどうか見当がつかず、「通ったから合ってるんだろう、たぶん」の境地です。

<?php
// 自分の得意な言語で
// Let's チャレンジ!!
$s = explode(" ",trim(fgets(STDIN)));
$h = $s[0];
$w = $s[1];
$l_num = $s[2];
$con = 0;//reset カウント
$hatena_flag = false;// ?にしたかどうか
//map取得
for ($i = 0; $i < $h; $i++) {
$hoge = trim(fgets(STDIN));
for ($j = 0; $j < $w; $j++) {
$map[$i][$j] = mb_substr($hoge, $j, 1);
if($map[$i][$j]=="*"){
$y = $i;
$x = $j;
}
}
}
//l取得
for ($i = 0; $i < $l_num; $i++) {
$hatena[] = trim(fgets(STDIN));
}
//print_r($hatena);
//初期位置に対して
if($hatena[0] == $con){
$map[$y][$x] = "?";
array_shift($hatena);
}else{
$map[$y][$x] = "*";
}
$con++;
//print_r($map);
//初期処理
//新たに*にした場所を$newstarに格納する
if($con == $hatena[0]){
$put_text = "?";
if(count($hatena)>=1){
array_shift($hatena);//使用済みにつきひとつ消去
}
}else{
$put_text = "*";
}
if($y>=1 && $map[$y-1][$x]=="."){
$map[$y-1][$x] =$put_text;
$newstar[]=array($y-1,$x, $con);
}
if($y<$h-1 && $map[$y+1][$x]=="."){
$map[$y+1][$x] = $put_text;
$newstar[]=array($y+1,$x, $con);
}
if($x>=1 && $map[$y][$x-1]=="."){
$map[$y][$x-1] = $put_text;
$newstar[]=array($y,$x-1, $con);
}
if($x<$w-1 && $map[$y][$x+1]=="."){
$map[$y][$x+1] = $put_text;
$newstar[]=array($y,$x+1, $con);
}
//print_r($newstar);
//echo($newstar[0][2]."\n");
while(count($newstar)>=1){//移動可能な配列がある限り続ける
$y = $newstar[0][0];
$x = $newstar[0][1];
$con = ($newstar[0][2])+1;
//?にするところかどうか
for($i=0; $i<count($hatena); $i++){
if($con == $hatena[$i]){
$hatena_flag = true;
}
}
if($hatena_flag == true){
$put_text="?";
}else{
$put_text="*";
}
//共通操作
if($y>=1 && $map[$y-1][$x]=="."){
$map[$y-1][$x] =$put_text;
$newstar[]=array($y-1,$x, $con);
}
if($y<$h-1 && $map[$y+1][$x]=="."){
$map[$y+1][$x] = $put_text;
$newstar[]=array($y+1,$x, $con);
}
if($x>=1 && $map[$y][$x-1]=="."){
$map[$y][$x-1] = $put_text;
$newstar[]=array($y,$x-1, $con);
}
if($x<$w-1 && $map[$y][$x+1]=="."){
$map[$y][$x+1] = $put_text;
$newstar[]=array($y,$x+1, $con);
}
array_shift($newstar);//いまつかった配列を消す
//print_r($newstar);
$hatena_flag = false;
}
//出力
for ($i = 0; $i < $h; $i++) {
for ($j = 0; $j < $w; $j++) {
echo($map[$i][$j]);
}
echo("\n");
}
?>
追加になった$l(ハテナマークの位置)の処理位置をちょっと間違えて、
かなり意地悪なcase4で引っかかりました。
それがくるとは!!

paizaAランクレベルアップメニュー(各言語あり)
2+