题解 | #合唱队形# java && c++ (小白向)
合唱队形
https://www.nowcoder.com/practice/0045cd3e39634a66ada63c2adeb49234
//本题用动态规划求解 (本人动规初学者以及c++初学者)
// 逆向思维 求最少出队人数
// 即为 求一个 →(箭头) 形状的数组 中间凸起 两边逐渐下降
// 方法:分别从两个方向求出 该方向的最长递增序列 然后 长出最长的箭头状态数组 数组长度 减去 子序列长度
// 定义 dp_left[n] dp_right[n] 两个数组 分别表示 从左右两个方向起 以第n个数结尾的最长递增子序列 n为数组长度
// 状态转移方程为 : if(inits[i] > inits[j])dp[i] = max(dp[i],dp[j]+1) 左右都一样,双循环嵌套
// 循环求该方向的最长递增子序列 当inits[i] > inits[j] 时,取 max 值的解释:
// dp[i] 用来存储最大值,不一定是dp【i-1】最大
//因为是最长 !递增!子序列 这个递增很重要 , 所以不能光第i个元素大于j元素就直接加,必须取决于前面元素的dp大小
// 186 186 150 200 160 130 197 220 例子中,前三个的 dp都为1 所以 200 的dp为 2
// 还有 1 2 4 3 5 3的dp为 3 , 但是 5 的dp为 5 ,要比大小取值dp
// 1 3 5 4 7 6 9
// dp-left初始值全设为 1 ,因为最小的子序列为其本身 ,dp-right 不设,全为零,防止重复计算
// 注意 c++中数组默认值不全为0,java的才全是零
//c++ 置零调用memset 方法
#include <bits/stdc++.h> //C++万能库
using namespace std;
int main() {
std::ios::sync_with_stdio(false); // 解除scanfprin 和 cin cout的同步
std::cin.tie(nullptr); //解除 cin cout的同步 都是增加速度
int nums;
cin>>nums;
int inits[nums];
for (int i = 0; i < nums; ++i) {
cin>>inits[i];
}
int dp_left[nums];
int dp_right[nums];
for (int i = 0; i < nums; ++i) {
dp_left[i] = 1;
}
for (int i = 0; i <nums ; ++i) {
for (int j = 0; j <i ; ++j) {
if (inits[i] > inits[j]){
dp_left[i] = max(dp_left[i],dp_left[j]+1);
}
}
}
memset(dp_right,0,sizeof (dp_right));
for (int i = nums-2; i >= 0 ; i--) {
for (int j = nums-1; j > i ; j--) {
if (inits[i] > inits[j]){
dp_right[i] = max(dp_right[i],dp_right[j]+1);
}
}
}
int Max = 1;
for (int i = 0; i < nums; ++i) {
Max = max(Max,dp_left[i]+dp_right[i]);
}
int ans = nums - Max;
cout<<ans;
return 0;
}
import java.io.*;
import java.util.Arrays;
public class Main {
public static void main(String[] args) throws IOException {
StreamTokenizer streamTokenizer =
new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(System.out));
streamTokenizer.nextToken();
int nums = (int) streamTokenizer.nval;
int[] ints = new int[nums];
for (int i = 0; i < nums; i++) {
streamTokenizer.nextToken();
ints[i] = (int) streamTokenizer.nval;
}
int[] dp_left = new int[nums];
int[] dp_right = new int[nums];
for(int i=0;i<nums;i++){
dp_left[i] =1;
}
for (int i = 1; i < nums; i++) {
for (int j = 0; j < i; j++) {
if (ints[i]>ints[j]){
dp_left[i] = Math.max(dp_left[i],dp_left[j]+1);
}
}
}
for (int i = nums-2; i >= 0; i--) {
for (int j = nums-1; j > i ; j--) {
if (ints[i]> ints[j]){
dp_right[i] = Math.max(dp_right[i],dp_right[j] + 1 );
}
}
}
int max = 0;
for (int i = 0; i < nums; i++) {
max = Math.max(max,dp_left[i] + dp_right[i]);
}
int out = nums - max;
printWriter.println(out);
printWriter.flush();
}
}
动态规划题解 文章被收录于专栏
个人动态规划题解合集
查看14道真题和解析