php实现 合唱队形(算法想清楚在动)

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

输入

复制
8
186 186 150 200 160 130 197 200

输出

复制
4

代码一:

 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 ?>
 
原文地址:https://www.cnblogs.com/Renyi-Fan/p/9228186.html