php实现 合唱队形(算法想清楚在动)
一、总结
一句话总结:写一个最长递增子序列的函数,正反两遍扫一下就好。写函数这样不容易错。这个好像可以用二分来优化。
1、算法题怎么提高正确率和节约时间?
算法想清楚了在做,不然会出现莫名其妙,稀奇古怪的错误。
2、php中如何填充数组?
用array_fill();
array array_fill ( int $start_index
, int $num
, mixed $value
)
$a = array_fill(5, 6, 'banana');
Array ( [5] => banana [6] => banana [7] => banana [8] => banana [9] => banana [10] => banana )
二、合唱队形
题目描述
计算最少出列多少位同学,使得剩下的同学排成合唱队形
说明:
N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足存在i(1<=i<=K)使得T1<T2<......<Ti-1<Ti>Ti+1>......>TK。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
输入描述:
整数N
输出描述:
最少需要几位同学出列
代码一:
1 <?php 2 //谋而后动,之前算法有问题 3 while($n=trim(fgets(STDIN))){ 4 $numStr=trim(fgets(STDIN)); 5 $arr=explode(' ',$numStr); 6 for($i=0;$i<$n;$i++){ 7 $gao[$i]=1; 8 $gaoRev[$i]=1; 9 } 10 //print_r($arr); 11 for($i=0;$i<$n;$i++){//遍历每一个人 12 for($j=0;$j<$i;$j++){//遍历他们前面的 13 if($arr[$i]>$arr[$j]&&$gao[$j]+1>$gao[$i]) $gao[$i]=$gao[$j]+1; 14 } 15 } 16 for($i=$n-1;$i>0;$i--){//遍历每一个人 17 for($j=$n-1;$j>$i;$j--){//遍历他们前面的 18 if($arr[$i]>$arr[$j]&&$gaoRev[$j]+1>$gaoRev[$i]) $gaoRev[$i]=$gaoRev[$j]+1; 19 } 20 } 21 for($i=0;$i<$n;$i++) $ans[$i]=$n+1-$gao[$i]-$gaoRev[$i]; 22 //print_r($gao); 23 //print_r($gaoRev); 24 echo min($ans).PHP_EOL; 25 } 26 27 ?>
代码二:
1 <?php 2 3 function lis($arr){ 4 $dp = array_fill(0,count($arr),1); 5 $ends = array_fill(0,count($arr),0); 6 $l = 0; $r = 0; $right = 0; 7 $ends[0] = $arr[0]; 8 for($i = 1; $i<count($arr);$i++) { 9 $l = 0; 10 $r = $right; 11 while ($l <= $r) { 12 $mid = floor(($l + $r)/2); 13 if($arr[$i]>$ends[$mid]) { 14 $l = $mid + 1; 15 }else { 16 $r = $mid - 1; 17 } 18 } 19 $right = max($right,$l); 20 $dp[$i] = $l+1 ; 21 $ends[$l] = $arr[$i]; 22 } 23 return $dp; 24 } 25 26 //两遍最长递增子序列 和最大 27 while (fscanf(STDIN,"%d",$N)) { 28 $T = explode(" ",trim(fgets(STDIN))); 29 $lis1 = lis($T); 30 $lis2 = lis(array_reverse($T)); 31 $lis2 = array_reverse($lis2); 32 for($i=0;$i<$N;$i++){ 33 $lis1[$i] += $lis2[$i]; 34 } 35 $max = max($lis1); 36 /* $dp1 = array_fill(0,$N,1); 37 $dp2 = array_fill(0,$N,1); 38 for($i=0;$i<$N;$i++){ 39 for($j=$i-1;$j>=0;$j--){ 40 if($T[$j]<$T[$i]&&$dp1[$j]+1>$dp1[$i]) 41 $dp1[$i] = $dp1[$j]+1; 42 } 43 } 44 $Tr = array_reverse($T); 45 for($i=0;$i<$N;$i++){ 46 for($j=$i-1;$j>=0;$j--){ 47 if($Tr[$j]<$Tr[$i]&&$dp2[$j]+1>$dp2[$i]) 48 $dp2[$i] = $dp2[$j]+1; 49 } 50 } 51 $dp2 = array_reverse($dp2); 52 53 $max = -1; 54 $sum = 0; 55 for($i=0;$i<$N;$i++){ 56 $sum = $dp1[$i]+$dp2[$i]; 57 if($sum>$max) 58 $max = $sum; 59 } */ 60 echo ($N-$max+1)." "; 61 62 } 63 ?>